openLuup: Shelly Bridge plugin
-
I added a one line of logging after line 296 & 297 like so:
function MQTT_packet.PUBLISH (TopicName, ApplicationMessage, control_flags) -- publish to MQTT client socket (with QoS = 0) _log ('Topic: '..TopicName..' ApplicationMessage: '..ApplicationMessage)
and here is the log edited to show the action:
CONNECT tcp{client}: 0x55a8931288 ClientId: shellyplusht-80646fc9b46d WillTopic: shellyplusht-80646fc9b46d/online WillMessage: false UserName: **** Password: **** CONNACK ack SUBSCRIBE tcp{client}: 0x55a8931288 Packet Id: 0x0001 Topic: shellyplusht-80646fc9b46d/rpc SUBACK ack shellyplusht-80646fc9b46d SUBSCRIBE to shellyplusht-80646fc9b46d/rpc tcp{client}: 0x55a8931288 SUBSCRIBE tcp{client}: 0x55a8931288 Packet Id: 0x0002 Topic: shellyplusht-80646fc9b46d/command/sys SUBACK ack shellyplusht-80646fc9b46d SUBSCRIBE to shellyplusht-80646fc9b46d/command/sys tcp{client}: 0x55a8931288 SUBSCRIBE tcp{client}: 0x55a8931288 Packet Id: 0x0003 Topic: shellyplusht-80646fc9b46d/command SUBACK ack shellyplusht-80646fc9b46d SUBSCRIBE to shellyplusht-80646fc9b46d/command tcp{client}: 0x55a8931288 SUBSCRIBE tcp{client}: 0x55a8931288 Packet Id: 0x0004 Topic: shellies/command SUBACK ack shellyplusht-80646fc9b46d SUBSCRIBE to shellies/command tcp{client}: 0x559c9277e8 PUBLISH tcp{client}: 0x559c9277e8 PUBACK ack Topic: shellyplusht-80646fc9b46d/online ApplicationMessage: true Topic: shellyplusht-80646fc9b46d/online ApplicationMessage: true PUBLISH tcp{client}: 0x559c9277e8 PUBACK ack Topic: shellyplusht-80646fc9b46d/events/rpc ApplicationMessage: {"src":"shellyplusht-80646fc9b46d","dst":"shellyplusht-80646fc9b46d/events","method":"NotifyFullStatus","params":{"ts":1.45,"ble":{},"cloud":{"connected":false},"devicepower:0":{"id": 0,"battery":{"V":0.43, "percent":0},"external":{"present":true}},"ht_ui":{},"humidity:0":{"id": 0,"rh":54.7},"mqtt":{"connected":true},"sys":{"mac":"80646fc9b46d","restart_required":false,"time":null,"unixtime":null,"uptime":1,"ram_size":246864,"ram_free":167876,"fs_size":458752,"fs_free":176128,"cfg_rev":11,"kvs_rev":0,"webhook_rev":0,"available_updates":{},"wakeup_reason":{"boot":"deepsleep_wake","cause":"status_update"},"wakeup_period":600},"temperature:0":{"id": 0,"tC":23.2, "tF":73.7},"wifi":{"sta_ip":"<ip_address>","status":"got ip","ssid":"<ssid>","rssi":-66},"ws":{"connected":false}}} Topic: shellyplusht-80646fc9b46d/events/rpc ApplicationMessage: {"src":"shellyplusht-80646fc9b46d","dst":"shellyplusht-80646fc9b46d/events","method":"NotifyFullStatus","params":{"ts":1.45,"ble":{},"cloud":{"connected":false},"devicepower:0":{"id": 0,"battery":{"V":0.43, "percent":0},"external":{"present":true}},"ht_ui":{},"humidity:0":{"id": 0,"rh":54.7},"mqtt":{"connected":true},"sys":{"mac":"80646fc9b46d","restart_required":false,"time":null,"unixtime":null,"uptime":1,"ram_size":246864,"ram_free":167876,"fs_size":458752,"fs_free":176128,"cfg_rev":11,"kvs_rev":0,"webhook_rev":0,"available_updates":{},"wakeup_reason":{"boot":"deepsleep_wake","cause":"status_update"},"wakeup_period":600},"temperature:0":{"id": 0,"tC":23.2, "tF":73.7},"wifi":{"sta_ip":"<ip_address>","status":"got ip","ssid":"<ssid>","rssi":-66},"ws":{"connected":false}}} PUBLISH tcp{client}: 0x559c9277e8 PUBACK ack Topic: shellyplusht-80646fc9b46d/events/rpc ApplicationMessage: {"src":"shellyplusht-80646fc9b46d","dst":"shellyplusht-80646fc9b46d/events","method":"NotifyStatus","params":{"ts":1.45,"mqtt":{"connected":true}}} Topic: shellyplusht-80646fc9b46d/events/rpc ApplicationMessage: {"src":"shellyplusht-80646fc9b46d","dst":"shellyplusht-80646fc9b46d/events","method":"NotifyStatus","params":{"ts":1.45,"mqtt":{"connected":true}}} PUBLISH tcp{client}: 0x559c9277e8 PUBACK ack Topic: shellyplusht-80646fc9b46d/events/rpc ApplicationMessage: {"src":"shellyplusht-80646fc9b46d","dst":"shellyplusht-80646fc9b46d/events","method":"NotifyEvent","params":{"ts":1703301404.25,"events":[{"component":"sys", "event":"sleep", "ts":1703301404.25}]}} Topic: shellyplusht-80646fc9b46d/events/rpc ApplicationMessage: {"src":"shellyplusht-80646fc9b46d","dst":"shellyplusht-80646fc9b46d/events","method":"NotifyEvent","params":{"ts":1703301404.25,"events":[{"component":"sys", "event":"sleep", "ts":1703301404.25}]}} MQTT:1883 connection closed tcp{client}: 0x559c9277e8 openLuup.mqtt:: RECEIVE ERROR: (Fixed Header byte) closed tcp{client}: 0x559c9277e8
Every 5 minutes the Shelly come on line, sends some status and finally sends the sleep mode event then goes into sleep mode. This would close the connection to the openLuup server. So I'm wondering if openLuup is checking for a "PUBACK" at this time and that's an issue? Might also be a QoS level mix up as well; eg "PUBACK" is not needed. Or the Shelly is going to sleep too early.
I'm still trying to understand how this all works and in what direction information is being sent eg is "PUBACK" been sent or received by openLuup. A few <-- arrows might be good --> eg incoming and outgoing.
And why does my log code line, log the same information twice in a row. I see it does this also for my Zigbee MQTT devices, which work fine. If openLupp is publishing one of its own internal variables the log only shows it once.
-
Yes - they are a nice unit. The large display is easy to read. This guy does a good rant on the Shelley MQTT info.
I also got one of these zigbee devices: Aqara temperature, humidity, TVOC air quality monitor. The latter has smaller display than the Shelley. Both devices give very similar temperature readings but a substantial 10% difference in the humidity readings. I can't be certain but it looks like the zigbee device is less likely to be showing the correct figure. You can add offsets, etc but not too sure how you would actually go about calibrating it.
-
Well I compared another Xiaomi humidity temperature device with the Shelley device and got a good match in the readings. It looks like the Shelly device and this particular Xiaomi device are literally out by the old software error factor of one ie a 10% difference. There is an OTA software update available but I can't get it to happen.
Anyway I got one of the hairs off my head and proceeded to calibrate it against the Shelly and the Xiaomi devices. I searched & searched and could only find a hair about 2 mm long. Complete waste of time. Maybe alopecia has set in?
Great to see the Gen3 device ( they've shrunk the kids once again) - looks like you have your work cut out for you re: openLuup. About a year from now; we'll get to see them on sale here where I live.
-
Good news and I still haven't forgotten about Zwave via MQTT! Starting point, at a minimum, would be:
- light on/off (although most are dimmers these days, but not all)
- blinds up/down - pretty much the same as the above
- general purpose outlets (GPO) - pretty much the same as the above
- minimotes
Some items may be returning power consumption info as well.
The above would cover the majority of stuff?
-
This error is looking very weird: the server says the socket is ready to read, but the read fails. I've added an extra check for the status just before the read, and it looks like this is, indeed, the case.
Apart from blaming a flakey LuaSocket module, I can't, as yet, think how this happens. So still working on it...
-
Latest development version (v24.2.8) now supports the Shelly Plus H&T. It should detect a new device when it is reset or generates a normal update. There is a parent Shelly device and temperature and humidity child devices.
The unexplained fixed header byte error remains, but it has no impact since the connection with the device is closed anyway, and the connection remade when the device wakes up again.
I have rounded the humidity reading to the nearest integer, since there's no way that it's that accurate.
-
Latest development version (v24.2.8) now supports the Shelly Plus H&T. It should detect a new device when it is reset or generates a normal update. There is a parent Shelly device and temperature and humidity child devices.
The unexplained fixed header byte error remains, but it has no impact since the connection with the device is closed anyway, and the connection remade when the device wakes up again.
I have rounded the humidity reading to the nearest integer, since there's no way that it's that accurate.
Tried out the latest software:
-
line 583: The newinfo.ip is null, so the software does a return and no device is created. I think, if a static address is set up in the Shelley, this may return an IP address. But I'm using DCHP with statics set there.
-
I bypassed the return code by setting the ip address to "1.1.1.1". At line 588 sys.device.name is null. So I gave it a fake name "Shelley_Name" regardless later on you seem to have populated with shellyplusht-<the_id>.
-
After setting up the bypass: the parent device was created with the two children. The handler is hit every five minutes and only stops running once it realises the device already exists in function init_device() at line 463. Can this exit be determined earlier in the handler (just my OCD on wasted CPU cycles)?
-
The children aren't populated. You have to subscribe to "shellyplusht-<the_id>/events/rpc". Refer to this guys vid. And then look specifically for the event that contains this "method": "NotifyFullStatus". It contains all the good info.
-
You can then get the temp & humidity and also the ip address. The battery info has a flag indicating if running of USB (ie 5 Volts) or not. The device id is the Mac address. When you read the mac address, it has had all the colons or dashes removed. Can they be put back in when the MAC address is stored in the device attributes?
Here is the NotifyFullStatus event json and after that I have attached the json used when the device is being created.
So making good progress.
{ "src": "shellyplusht-<the_id>", "dst": "shellyplusht-<the_id>/events", "method": "NotifyFullStatus", "params": { "ts": 9.37, "ble": {}, "cloud": { "connected": false }, "devicepower:0": { "id": 0, "battery": { "V": 0.43, "percent": 0 }, "external": { "present": true } }, "ht_ui": {}, "humidity:0": { "id": 0, "rh": 54.2 }, "mqtt": { "connected": true }, "sys": { "mac": "<the_id>", "restart_required": false, "time": null, "unixtime": null, "uptime": 9, "ram_size": 246872, "ram_free": 167920, "fs_size": 458752, "fs_free": 176128, "cfg_rev": 11, "kvs_rev": 0, "webhook_rev": 0, "available_updates": {}, "wakeup_reason": { "boot": "deepsleep_wake", "cause": "status_update" }, "wakeup_period": 600 }, "temperature:0": { "id": 0, "tC": 24.8, "tF": 76.7 }, "wifi": { "sta_ip": "the_IP", "status": "got ip", "ssid": "the_SID", "rssi": -75 }, "ws": { "connected": false } } }
Device creation - topic "shelly-gen2-cmd/rpc":
{ "id": "table: 0x55a8a880e0", "src": "shellyplusht-<the_id>", "dst": "shelly-gen2-cmd", "result": { "ble": { "enable": false, "rpc": { "enable": true } }, "cloud": { "enable": false, "server": "iot.shelly.cloud:6012/jrpc" }, "devicepower:0": {}, "ht_ui": { "temperature_unit": "C" }, "humidity:0": { "id": 0, "name": null, "report_thr": 5, "offset": 0 }, "mqtt": { "enable": true, "server": "server_ip:1883", "client_id": "shellyplusht-<the_id>", "user": null, "topic_prefix": "shellyplusht-<the_id>", "rpc_ntf": true, "status_ntf": false, "use_client_cert": false, "enable_rpc": true, "enable_control": true }, "sys": { "device": { "name": null, "mac": "<the_id>", "fw_id": "20231106-160224/1.0.8-gdba0ee3", "discoverable": true }, "location": { "tz": "some-place", "lat": "lat", "lon": "lon" }, "debug": { "level": 2, "file_level": null, "mqtt": { "enable": false }, "websocket": { "enable": false }, "udp": { "addr": null } }, "ui_data": {}, "rpc_udp": { "dst_addr": null, "listen_port": null }, "sntp": { "server": "time.google.com" }, "cfg_rev": 11 }, "temperature:0": { "id": 0, "name": null, "report_thr_C": 0.5, "offset_C": 0 }, "wifi": { "ap": { "ssid": "ShellyPlusHT-<the_id>", "is_open": true, "enable": false }, "sta": { "ssid": "some_SID", "is_open": false, "enable": true, "ipv4mode": "dhcp", "ip": null, "netmask": null, "gw": null, "nameserver": null }, "sta1": { "ssid": null, "is_open": true, "enable": false, "ipv4mode": "dhcp", "ip": null, "netmask": null, "gw": null, "nameserver": null }, "roam": { "rssi_thr": -80, "interval": 60 } }, "ws": { "enable": false, "server": null, "ssl_ca": "ca.pem" } } }
-
-
IP was used for HTTP request to get device name in an early version, and that piece of code remained.
The whole point of MQTT is that it doesn’t need one, of course.
Edit: It is, however, used to the browser window in the openLuup device page of the parent device, so that you can interact directly with the it for firmware updates, etc..