Shellies Discovery Gen2 Script

Thank you for your help Release Version 2.11.0 · bieniu/ha-shellies-discovery-gen2 · GitHub

It’s thanks to you. works perfectly!
image

1 Like

Seems they support announce when “Enable MQTT Control” is enabled. My Shelly Plus 1PM reacts to an announce message to shellies/command. Perhaps fully automatic discovery is possible this way?

[Session 1] pi@pi4:~ $ mosquitto_pub -t shellies/command -m announce

[Session 2, started before] pi@pi4:~ $ mosquitto_sub -t 'shellies/#' -v
shellies/command announce
shellies/announce {"name":null,"id":"shellyplus1pm-xxxxxxxxxxxx","mac":"xxxxxxxxxxxx","slot":1,"model":"SNSW-001P16EU","gen":2,"fw_id":"20230718-125048/1.0.0-beta6-g4893033","ver":"1.0.0-beta6","app":"Plus1PM","auth_en":false,"auth_domain":null}

I am using 1.0.0-beta6 firmware, but I think this was already working with 0.14.0.

Shellies Discovery Gen2 is using Shelly.GetConfig service to configure the device, not announce payload. Announce payload has insufficient data.

Sure, but would it be possible to just determine which gen2 devices are available at all through the announce payload, so that it is unnecessary to list each one in the configuration under device_ids.

The announce paylod at least delivers the device ID. The shellies_announce_gen2 automation could collect all gen2 devices through announce and then configure each one with the Shelly.GetConfig call. I will give it a try and let you know if this works.

This seems to work - I tried to integrate Gen1+2 together, but could not test yet with Gen1 (will have to wait until tomorrow when I can setup a Shelly 1L).

It automatically configures all announced Gen2 devices with RPC and Shelly.GetConfig , and all Gen1 devices as before, with your two Python scripts. The additional 5 s delay in the announce script makes sure that the two MQTT subscription automations are ready to when the announcement is published from shellies_announce_gen1_2. I do not know if there is a more elegant way to wait until the two other automations are ready to go.

- id: shellies_announce_gen1_2
  alias: 'Shellies Announce Gen1+2'
  trigger:
    - platform: homeassistant
      event: start
    - platform: time_pattern
      hours: "/1"  # Modifying this if you are using Shelly Motion can drain your device's battery quickly.
  action:
    - delay: 5   # Delay 5 seconds to allow MQTT listener automations to start up
    - service: mqtt.publish
      data:
        topic: shellies/command
        payload: announce

- id: 'shellies_discovery_gen1_2'
  alias: 'Shellies Discovery Gen1+2'
  mode: queued
  max: 999
  trigger:
    platform: mqtt
    topic: shellies/announce
  variables:
    device_info_payload:  "{{ {'id': 1, 'src':'shellies_discovery', 'method':'Shelly.GetConfig'} | to_json }}"
  action:
    - choose:
        # IF gen1 device:
        - conditions:  
            - condition: template
              value_template: "{{ trigger.payload_json.gen is not defined }}"
          sequence:
            - service: python_script.shellies_discovery
              data:
                id: '{{ trigger.payload_json.id }}'
                mac: '{{ trigger.payload_json.mac }}'
                fw_ver: '{{ trigger.payload_json.fw_ver }}'
                model: '{{ trigger.payload_json.model | default }}'
                mode: '{{ trigger.payload_json.mode | default }}'
                host: '{{ trigger.payload_json.ip }}'
        # ELIF gen2 device:
        - conditions:
            - condition: template
              value_template: "{{ trigger.payload_json.gen==2 }}"
          sequence:
            - service: mqtt.publish
              data:
                topic: "{{ trigger.payload_json.id }}/rpc"
                payload: "{{ device_info_payload }}"

- id: shellies_install_script_gen2
  alias: "Shellies Install Script Gen2"
  mode: queued
  max: 999
  trigger:
  - platform: mqtt
    topic: shellies_discovery/rpc
  action:
  - service: python_script.shellies_discovery_gen2
    data:
      id: "{{ trigger.payload_json.src }}"
      device_config: "{{ trigger.payload_json.result }}"

What about devices with custom MQTT prefix?

I will try tomorrow - I think it should work OK, I suppose the custom prefix will be passed through the id field in the shellies/announce response.

Update: does not work when MQTT prefix is modified - the id in the shellies/announce message remains the client ID (shellyplus1pm-xxxxxxxxxxxx). Still, the second announce message goes to newtopic/subtopic/announce.

So, back to square one :frowning: At least, it is great opportunity to learn MQTT and automations.

That’s what I was afraid of, I asked Shelly a long time ago to increase the amount of data in announce payload but they didn’t agree.

I think with some small change it will work nevertheless: according to documentation RPC Channels | Shelly Technical Documentation Shelly will listen to <shelly-id>/rpc regardless of MQTT topic prefix configuration. I will try it this evening.

Honestly, I’m happy with the current solution. If you have an idea for improvement, PR is most welcome!

Your script ist great, I just dislike the idea of having to add 20-30 device IDs manually to the HA configuration.

After some testing, it seems that - contrary to the Shelly Gen2 API documentation - they do not listen on <shelly-id>/rpc but on <mqtt-prefix>/rpc for RPC calls.

This is bad, because they only announce the shelly-id. So unless both shelly-id and mqtt-prefix are changed identical, the automatic discovery cannot work - only solution I can currently imagine would be to scan all retained LWT online messages and check each one with a RPC call “into the blue”.

Maybe I should ask Shelly support about this, seems their API docu is wrong there.

For my purposes, the modification works well enough for now, as I do not want to modify the MQTT topic anyway.

Hi, i have a small issue with the discovered devices.
It looks like none of the devices have the “Firmware” entity working, it’s always in “Unknown” state.
image

Do I need to enable something on the Shelly side?

Hi, first thank you for your great work on this script.
This script works well for me on all 2pm devices except on the one where I set custom MQTT prefix.
I set the custom prefix on the device_ids list and the script find the device and it appears under the HA MQTT devices. However I cannot control it, because all of the commands goes out under the [deviceid] topic instead of the custom topic.
Therefore in MQTT explorer I see the device under two different topics: the custom topic, where I can see its announcement and the original [deviceid] topic where I can see all of the commands I send out to the device.
What I miss in the configuration?

Show me your config and debug log for python script component.

Thanks for pointing me to the log. The firmware was old on the device, that caused the issues :slight_smile:

1 Like

Hi!

Did you get this to work?
Having the same issue, two button on and off insted of toggle switch.

Also not sure what Bieniu ment with “After first update of the relay”, probably here is the awnser but I cant figure it out.

Thanks,

It means, after the device sends the information about the relay state.

Probably doing something stupid, but i just cannot get this to work. Any ideas? Need more info?

2023-09-26 22:50:06.220 INFO (MainThread) [homeassistant.components.automation.shellies_discovery_gen2] Shellies Discovery Gen2: Running automation actions
2023-09-26 22:50:06.220 INFO (MainThread) [homeassistant.components.automation.shellies_discovery_gen2] Shellies Discovery Gen2: Executing step call service
2023-09-26 22:50:06.368 INFO (SyncWorker_3) [homeassistant.components.python_script] Executing shellies_discovery_gen2.py: {'id': 'ShellyWallDisplay-xxxxxxxxxxxx', 'device_config': {'ble': {'rpc': {'enable': True}, 'observer': {'enable': False}}, 'wifi': {'sta': {'enable': True, 'ipv4mode': 'dhcp', 'ssid': 'xxxxxx', 'is_open': False, 'ip': '192.168.1.xxx', 'netmask': '255.255.255.0', 'gw': '192.168.1.1', 'nameserver': '192.168.1.1'}, 'sta1': {'enable': False, 'ssid': '', 'is_open': False, 'ipv4mode': 'dhcp'}}, 'switch:0': {'initial_state': 'restore_last', 'id': 0, 'auto_on': False, 'auto_on_delay': 0, 'auto_off': False, 'auto_off_delay': 0, 'in_mode': 'follow'}, 'input:0': {'id': 0, 'name': '', 'type': 'switch', 'invert': False, 'factory_reset': True}, 'temperature:0': {'id': 0, 'name': '', 'report_thr_C': 1, 'offset_C': 0}, 'humidity:0': {'id': 0, 'name': '', 'report_thr': 1, 'offset': 0}, 'illuminance:0': {'id': 0, 'name': '', 'bright_thr': 300, 'dark_thr': 100}, 'ui': {'lock_type': 'none', 'disable_gestures_when_locked': False, 'show_favourites': True, 'show_main_sensor_graph': True, 'use_F': False, 'screen_saver': {'enabled': False, 'timeout': 20, 'show_clock': True, 'show_humidity': True, 'show_temperature': True}}, 'sys': {'location': {'tz': 'Europe/xxxx', 'lat': xxx, 'lon': xxxx}, 'device': {'mac': 'xxxxxxxxxxx', 'fw_id': '20230815-161731/1.2.1-ef519c0', 'discoverable': False}, 'sntp': {'server': 'time.google.com'}, 'debug': {'websocket': {'enable': True}, 'mqtt': {'enable': True}, 'logs': {'Generic': False, 'Bluetooth': False, 'Cloud': False, 'Interface': False, 'Network': False, 'RPC': False, 'Screen': False, 'Webhooks': False, 'WebSocket': True}}, 'cfg_rev': 33}, 'cloud': {'enable': True, 'server': 'shelly-2-eu.shelly.cloud:6022/jrpc'}, 'mqtt': {'enable': True, 'user': 'Mqtt', 'server': '192.168.1.xxx:1883', 'client_id': 'ShellyWallDisplay', 'topic_prefix': 'ShellyWallDisplay-xxxxxxxx', 'rpc_ntf': True, 'status_ntf': True, 'debug': True, 'pass': 'MQTTmqtt1'}, 'ws': {'enable': False, 'ssl_ca': 'ca.pem'}}}
2023-09-26 22:50:06.368 ERROR (SyncWorker_3) [homeassistant.components.python_script.shellies_discovery_gen2.py] Error executing script: 'name'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/python_script/__init__.py", line 224, in execute
exec(compiled.code, restricted_globals) # noqa: S102
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "shellies_discovery_gen2.py", line 2571, in <module>
File "/usr/local/lib/python3.11/site-packages/RestrictedPython/Eval.py", line 28, in default_guarded_getitem
return ob[index]
~~^^^^^^^
KeyError: 'name'