maxime1992 / linak-2-mqtt

41 stars 8 forks source link

Linak2MQTT

Credits: This project wouldn't have been possible without the incredible work done by @rhyst on the idasen-controller project :heart:. Don't forget to give him a :star:!

Table of content

Setup

Prerequisites

Bluetooth initial setup

Your host must have your desk paired and trusted as a bluetooth device first.
The reason for that being: When starting out the docker we give access to the bluetooth dongle and all the config. This way the docker image is able to connect to the desk straight away.

From the host:

Example of output while the scan is on

Discovery started
[CHG] Controller XX:XX:XX:XX:XX:XX Discovering: yes
[CHG] Device XX:XX:XX:XX:XX:XX RSSI: -83
[CHG] Device XX:XX:XX:XX:XX:XX RSSI: -71
[NEW] Device XX:XX:XX:XX:XX:XX Desk 7734 <-- notice the [NEW] here
[CHG] Device XX:XX:XX:XX:XX:XX RSSI: -75
[CHG] Device XX:XX:XX:XX:XX:XX RSSI: -95

And from here you should see the prompt like this [Desk 7734]# meaning you're connected to the desk, at which point you must disconnect from it by typing [Desk 7734]# disconnect

All the configuration on the side of the host is now done and you should not have to manipulate anything here anymore.

Run the docker image

The docker image will connect to your desk and interact with it through MQTT so that you can interact with it the way you want.

Before building and launching it:

Then:

MQTT interactions

You can listen to:

You publish to:

Home Assistant integrations

The MQTT API ensure you can build any kind of integration you'd like. Speaking for myself, I've chosen to use Home Assistant. In this seection I'll explain how to specifically integrate your desk in Home Assistant and give some examples of automations.

Lovelace linak-desk-card

@IhorSyerkov has built a great (interactive) Lovelace card:

Desk in sitting position Desk in standing position
Desk in sitting position Desk in standing position

This was originally built to integrate with ESPHome idasen-desk-controller (see linak-desk-card's documentation), but I didn't want to have using another device hence why I built my own solution.

That's why we've got a little bit of configuration to make on Home Assistant in order to have the card working properly.

mqtt:
  sensor:
    - name: linak_desk_height
      state_topic: 'linak-2-mqtt/desk-relative-height-updated'
  binary_sensor:
    - name: is_desk_available
      state_topic: 'linak-2-mqtt/desk-relative-height-updated'
      off_delay: 100
      value_template: "{{ 'online' }}"
      payload_on: 'online'
      payload_off: 'offline'

On your dashboard, we'll now create a new card:

type: custom:linak-desk-card
min_height: 62
max_height: 127
presets:
  - label: Stand
    target: 120
  - label: Sit
    target: 73
name: Desk
height_sensor: sensor.linak_desk_height
connection_sensor: binary_sensor.is_desk_available
# @todo not implemented because I'm unsure what that'll change and it's not a priority for now
# moving_sensor: binary_sensor.is_desk_moving
desk: cover.desk

Important note:

Make sure the config above matches:

This is slightly annoying to have some configuration duplicated but I haven't found a better option for now and it's not something you'll need to edit all the time.

Everything we did so far was in order to get the correct height displayed on the desk card. Now lets hook the 2 buttons stand and sit so we're able to control the desk from that card as well.

In order to do that, you'll need to create the following automation:

alias: 'Desk: Bind cover.set_cover_position to MQTT'
description: ''
trigger:
  - platform: event
    event_type: call_service
    event_data:
      domain: cover
      service: set_cover_position
condition: []
action:
  - service: mqtt.publish
    data:
      topic: linak-2-mqtt/set-desk-height
      payload_template: >
        {% set service_data =
        trigger.event.as_dict().get('data').get('service_data') %} {{
        ((service_data.get('position') * (127 - 62) / 100) + 62) | round(0) }}
mode: single

Note: Same here, it'd be nice to get the 127 (max height) and 62 (min height) from the card config if possible but I haven't done it for now.

Toggle the current position between sit and up using an NFC tag

alias: 'Tag Desk: Toggle desk position'
description: ''
trigger:
  - platform: tag
    tag_id: YOUR-TAG-ID-HERE
condition: []
action:
  - service: mqtt.publish
    data:
      topic: linak-2-mqtt/toggle-desk-position
mode: single

Automatically put the desk up for daily standup meetings

Last but not least, if you have some daily standup meeting for example, you could automatically put the desk up at that time if:

All this should let you avoid unnecessary triggers.

alias: 'Desk: Standing position at standup time on workday if I am home'
description: ''
trigger:
  - platform: time
    at: '10:59:00'
condition:
  - condition: zone
    entity_id: device_tracker.PHONE_TRACKER_HERE
    zone: zone.home
  - condition: state
    entity_id: binary_sensor.workday_sensor
    state: 'on'
  - condition: state
    entity_id: input_boolean.shoulddeskgostandingpositiononworkdaysifiamhome
    state: 'on'
action:
  - service: mqtt.publish
    data:
      topic: linak-2-mqtt/set-desk-height
      payload: '120'
mode: single

Don't forget to create both:

binary_sensor:
  # ... your other binary sensors
  - platform: workday
    name: workday_sensor
    country: FR
    workdays: [mon, tue, wed, thu, fri]
    excludes: [sat, sun]

Here's an example of complete dashboard:

Desk dashboard

- theme: Backend-selected
  title: Office
  path: office
  badges: []
  cards:
    - type: custom:linak-desk-card
      min_height: 62
      max_height: 127
      presets:
        - label: Stand
          target: 120
        - label: Sit
          target: 73
      name: Desk
      height_sensor: sensor.linak_desk_height
      connection_sensor: binary_sensor.is_desk_available
      moving_sensor: binary_sensor.linak_desk_moving
      desk: cover.desk
    - type: entities
      entities:
        - entity: input_boolean.shoulddeskgostandingpositiononworkdaysifiamhome
          name: Automatically go up at standup time?
      title: Desk
      show_header_toggle: false
      state_color: false
    - type: entities
      entities:
        - entity: binary_sensor.workday_sensor
          name: Is today a work day?
          icon: mdi:office-building
      state_color: false

Troubleshooting issues

If the logs show

[debug] Connected
starting idasen server...
Connecting
Connecting failed
Device with address XX:XX:XX:XX:XX:XX was not found.

Either:

Useful links