devWaves / SwitchBot-MQTT-BLE-ESP32

Allows for multiple SwitchBot bots and curtains to be controlled via MQTT sent to ESP32. ESP32 will send BLE commands to switchbots and return MQTT responses to the broker. Also supports Temperature, Motion, Contact sensors
MIT License
549 stars 68 forks source link

[feature request] Home Assistant MQTT discover #4

Closed Schluggi closed 3 years ago

Schluggi commented 3 years ago

Hi,

first of all: Thank you so much for this project! It works like a charm. :+1:

HomeAssistant has a MQTT discover feature. I would love to see this in your project. https://www.home-assistant.io/docs/mqtt/discovery/

devWaves commented 3 years ago

I had issues with the long JSON required for mqtt discovery. I might take another look, but at the time I couldn't figure out why. I had to shorten the buffer and JSON payload length

HardcoreWR commented 3 years ago

As a matter of fact I'm actually currently working on this. I cloned the repo 3 days ago and I wanted to get that working as a challenge :-) (and because I use HA myself as well)

I'm no professional programmer so it might take a while before I get this completely finished. The thing I wasn't sure about is how MQTT Discovery would work with the current code, so I've been rewriting it so we have topics such as switchbot/cover/curtain_left/state that has the state (just how it currently is, but in a state topic) and it listens on switchbot/cover/curtain_left/set for actions which can be any of PRESS, ON, OFF, OPEN, CLOSE, 0-100

devWaves commented 3 years ago

As a matter of fact I'm actually currently working on this

cool, good luck. if you beat me to it I'll look at pulling in the updates

the previous issues when I tried may have been related to the fact I was using String objects and ran out of memory

HardcoreWR commented 3 years ago

cool, good luck. if you beat me to it I'll look at pulling in the updates

the previous issues when I tried may have been related to the fact I was using String objects and ran out of memory

I made some progress on this. The default buffer size was set to 256 and when we publish the appropriate data to a topic this would easily exceed that. Adding client.setMaxPacketSize(65535); changes the buffer size and allowed me to succesfully auto discover my 2 SwitchBot Curtains. I will tweak this number at a later stage, when everything is working properly, to a more sane buffer size.

The only issues I'm having right now is that;

image

Schluggi commented 3 years ago

I can't control the curtain when clicking on the entity so I need to figure out why that's happening as well. There no position slider and no open, stop, close buttons.

I think you missed the extra properties like set_cover_position. Here is my switchbot curtain home assistant config. I guess you have to pass the properties in the discovery too.

https://www.home-assistant.io/integrations/cover.mqtt/

sensor:
  - platform: mqtt
    name: curtain_bedroom_left
    state_topic: "switchbot/curtain/curtain_bedroom_left"
    value_template: "{{ value_json.pos }}"
    json_attributes_topic: "switchbot/curtain/curtain_bedroom_left"

cover:
  - platform: template
    covers:
      bedroom_left:
        device_class: curtain
        friendly_name: Schlafzimmervorhang links
        position_template: "{{ states('sensor.curtain_bedroom_left') }}"
        set_cover_position:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload_template: '{ "id": "curtain_bedroom_left", "value": "{{ position }}" }'
        open_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "open" }'
        close_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "close" }'
        stop_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "pause" }'
        icon_template: >-
          {% if states('sensor.curtain_bedroom_left') | int < 10 %}
            mdi:window-shutter-open
          {% else %}
            mdi:window-shutter
          {% endif %}

Notice: The positions is not that precise while the curtain is moving. The MQTT topic does not return the position while moving:

{
  "id": "curtain_bedroom_left",
  "status": "info",
  "rssi": -67,
  "calib": true,
  "batt": 66,
  "pos": 0,
  "light": 1
}

While moving:

{
    "id":"curtain_bedroom_left",
    "status":"20"
}

There more examples where the output is not unified. Please fix ;)

HardcoreWR commented 3 years ago

Okay, I forked this repo earlier today (https://github.com/HardcoreWR/SwitchBot-MQTT-BLE-ESP32) and I just pushed my changes. I don't have a Switchbot Bot and a Switchbot Meter (yet) so I couldn't test their MQTT Discovery config. However, this is currently implemented by an educated guess.

I'm going to submit a Pull Request (it's my first one so forgive me if I'm doing anything wrong here :-) )

devWaves commented 3 years ago

cool. I only have the bot but I'll try to test later

marithpl commented 3 years ago

When the MQTT discovery will be release?

devWaves commented 3 years ago

whenever testing is complete and it works as expected. More testing will be done in the next few days

Schluggi commented 3 years ago

I just notice two bugs in my cover configuration.

Here is the new one:

sensor:
  - platform: mqtt
    name: curtain_bedroom_left
    state_topic: "switchbot/curtain/curtain_bedroom_left"
    value_template: "{{ 100 - (value_json.pos | int) }}" #  <--------------------
    json_attributes_topic: "switchbot/curtain/curtain_bedroom_left"

  - platform: mqtt
    name: curtain_bedroom_right
    state_topic: "switchbot/curtain/curtain_bedroom_right"
    value_template: "{{ 100 - (value_json.pos | int) }}" #  <--------------------
    json_attributes_topic: "switchbot/curtain/curtain_bedroom_right"

cover:
  - platform: template
    covers:
      bedroom_left:
        device_class: curtain
        friendly_name: Schlafzimmervorhang links
        position_template: "{{ states('sensor.curtain_bedroom_left') }}"
        set_cover_position:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload_template: '{ "id": "curtain_bedroom_left", "value": "{{ position }}" }'
        open_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "open" }'
        close_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "close" }'
        stop_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "pause" }'
        icon_template: >-
          {% if states('sensor.curtain_bedroom_left') | int > 10 %}
            mdi:window-shutter-open
          {% else %}
            mdi:window-shutter
          {% endif %}

      bedroom_right:
        device_class: curtain
        friendly_name: Schlafzimmervorhang rechts
        position_template: "{{ states('sensor.curtain_bedroom_right') }}"
        set_cover_position:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload_template: '{ "id": "curtain_bedroom_right", "value": "{{ position }}" }'
        open_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_right", "value": "open" }'
        close_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_right", "value": "close" }'
        stop_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_right", "value": "pause" }'
        icon_template: >-
          {% if states('sensor.curtain_bedroom_right') | int > 10 %}
            mdi:window-shutter-open
          {% else %}
            mdi:window-shutter
          {% endif %}

Edit: curtain was the right device_class. https://www.home-assistant.io/integrations/cover/

marithpl commented 3 years ago

I just notice two bugs in my cover configuration.

  • There is no device_class curtain. cover is the correct one.
  • In HA, the cover is closed on pos 0 but the switchbot curtain return closed on pos 100. So i had to change the values for the sensors. This will probably also wrong in the PR (i haven't checked).

Here is the new one:

sensor:
  - platform: mqtt
    name: curtain_bedroom_left
    state_topic: "switchbot/curtain/curtain_bedroom_left"
    value_template: "{{ 100 - (value_json.pos | int) }}" #  <--------------------
    json_attributes_topic: "switchbot/curtain/curtain_bedroom_left"

  - platform: mqtt
    name: curtain_bedroom_right
    state_topic: "switchbot/curtain/curtain_bedroom_right"
    value_template: "{{ 100 - (value_json.pos | int) }}" #  <--------------------
    json_attributes_topic: "switchbot/curtain/curtain_bedroom_right"

cover:
  - platform: template
    covers:
      bedroom_left:
        device_class: cover #  <--------------------
        friendly_name: Schlafzimmervorhang links
        position_template: "{{ states('sensor.curtain_bedroom_left') }}"
        set_cover_position:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload_template: '{ "id": "curtain_bedroom_left", "value": "{{ position }}" }'
        open_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "open" }'
        close_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "close" }'
        stop_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_left", "value": "pause" }'
        icon_template: >-
          {% if states('sensor.curtain_bedroom_left') | int > 10 %}
            mdi:window-shutter-open
          {% else %}
            mdi:window-shutter
          {% endif %}

      bedroom_right:
        device_class: cover #  <--------------------
        friendly_name: Schlafzimmervorhang rechts
        position_template: "{{ states('sensor.curtain_bedroom_right') }}"
        set_cover_position:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload_template: '{ "id": "curtain_bedroom_right", "value": "{{ position }}" }'
        open_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_right", "value": "open" }'
        close_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_right", "value": "close" }'
        stop_cover:
          service: mqtt.publish
          data:
            topic: switchbot/control
            payload: '{ "id": "curtain_bedroom_right", "value": "pause" }'
        icon_template: >-
          {% if states('sensor.curtain_bedroom_right') | int > 10 %}
            mdi:window-shutter-open
          {% else %}
            mdi:window-shutter
          {% endif %}

I found the same. When curtain is closed it show only down button which means closing. So I have to click in entity details and move curtains by the scroll.

I have a little problem with position status updates. It take so long time.

Schluggi commented 3 years ago

@marithpl

I have a little problem with position status updates. It take so long time.

This happens because of the problem mentioned here. In a nutshell: The pos attribute is not always part of the mqtt payload. Only if the switchbot is idle i think. That's why you have to wait so long. @devWaves Maybe something for v2 as well ;)

HardcoreWR commented 3 years ago

There are a few issues that I'm looking into at how to fix.

devWaves commented 3 years ago

I added a check if bots are in press mode it will send state OFF as soon as command is successful

I also fixed rescanTimes. It wasn't doing 30 seconds if bots was not in list