Getting proper power state checking with Sonoffs and builtin MQTT broker with Node-Red

If you are using any sonoff switches with the built in MQTT broker in Home Assistant, you would notice that power states are not tracked properly after Home Assistant is restarted.

Any switch that is on will be marked as off in Home Assistant until you toggle the switch.

Sonoffs do send telemetry MQTT messages with their current state, but Home Assistant ignores them.

Since I’m already using Node-Red for automations, the below code will reformat these telemetry MQTT messages and keep the power state up to date – Within a few minutes of any Home Assistant restart, the correct power state will be reflected.

Also this gets away from having to run Mosquitto as a MQTT broker and deal with the retain flag all together – having some messages retained can lead to weird results if the cmnd MQTT messages get replayed.

Here is the flow in Node Red:

[{"id":"19d621f6.09260e","type":"comment","z":"8bb76918.ef6b48","name":"Convert MQTT Telemetry Messages to State","info":"","x":190,"y":2320,"wires":[]},{"id":"33aa3552.76201a","type":"mqtt in","z":"8bb76918.ef6b48","name":"All MQTT Messages","topic":"#","qos":"1","broker":"4238db6e.227ed4","x":110,"y":2360,"wires":[["69bba69f.48a888"]]},{"id":"69bba69f.48a888","type":"function","z":"8bb76918.ef6b48","name":"Reformat telemetry to state","func":"tele_check = /^tele/;\npower_check = /POWER/g;\n\nif (tele_check.test(msg.topic) && power_check.test(msg.payload)) {\n new_payload = msg.payload.replace(/.*POWER..\\\"([A-Z]+)\\\".*/, '$1');\n msg.payload = new_payload;\n\n new_topic = msg.topic.replace(/(\\w+).(\\w+).(\\w+)/, 'stat/$2/POWER');\n msg.topic = new_topic;\n \n msg.altered = 1;\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":400,"y":2360,"wires":[["cd96ee57.d5f1f"]]},{"id":"cd96ee57.d5f1f","type":"switch","z":"8bb76918.ef6b48","name":"If message reformatted","property":"altered","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"}],"checkall":"true","outputs":1,"x":690,"y":2360,"wires":[["34dbbf1a.b7301"]]},{"id":"34dbbf1a.b7301","type":"mqtt out","z":"8bb76918.ef6b48","name":"Inject altered message","topic":"","qos":"","retain":"","broker":"4238db6e.227ed4","x":980,"y":2360,"wires":[]},{"id":"4238db6e.227ed4","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"node-red","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]

2 Likes

Thanks, Just set this up.

1 Like

No need for any of that, you just set PowerRetain to 1 on the Sonoff and HA corrects itself after restarting.

The built-in broker doesn’t honor the retain flag.

Only have personal experience of the hassio add on which works perfectly with it to be fair, but there’s plenty of mentions of it working with the old one so I guess there must be something more to your setup.

The HBMQTT docs reference retain flag, but it’s broken from home assistant (maybe outside of HASS.IO). Lots of other threads on it.