I am housing all of my Smarthome logic in Node-Red. I control devices connected to Zigbee2MQTT, Homebridge, and Hubitat there.
A simple example of something I am looking to do is as follows:
When a button is pushed toggle a bulb between off and on.
I know how to do this when everything is connected to the Hubitat. Basically the logic is as follows:
Receive the button push event
Check current state of bulb
If on send off command
If off send on command
All of these have very clear analogies on how to accomplish them if the button and bulb are connected to Zigbee2MQTT, with 1 exception. That is step 2.
Is there a method via MQTT to retrieve the current state?
I don’t think there is.I think what I need to do is capture the state when it is sent by Z2M on a change and store it in Node-Red and then reference that stored value for step 2. I just wanted confirmation that I wasn’t missing something obvious.
(I asked in Zigbee2MQTT forum and am not getting any reply a day later)
think you are right because if not the state of the bulb and your state might differ (other device changing the state or communication error)
A I read the doc you should be able to get the state:
I would wire the status topic (Mqtt in) to the input of a dashboard switch and the output to the /set topic (mqtt out).
Be aware to uncheck the pass msg option (or you risk a feedback loop) and set the show state to the input state.
If zigbee set the retain flag of the state topic the switch should always represent the actual state of the bulb.
Thanks for the feedback. I think we are on the same page that there isn’t an easy and overlooked way to get the state on demand, but there are many ways like the dashboard switch to,store it internal to node red.
I suggested the dashboard switch for testing purposes only. You will have visual feedback.
Later you can store the last received message in flow or global context and use that for your toggle function
The conventional way to solve that without using context is to feed the button and the current state (with different topics) into a Join node configured as below. Then you will get out of the Join node a message containing both the event and the current state, each time the button is pressed or the state changes. Feed that into a Switch node configured to only pass if the topic matches the button press. Then you will have a message each time the button is pressed, that contains the the current state, so you can then test it and take appropriate action.
However, are you sure you would not be better with a ui-switch rather than a button. If you feed the current state into the front of the switch you can get it to always show the state matching the real world, and when you click it the state will change and the output will automatically be correct, since the switch is starting in the correct position. This has the additional advantage that if the state is changed externally to node-red then the switch will automatically follow.
Configure the switch to not pass through messages (otherwise you may well get an MQTT loop) and to show the state of the input rather than the output. There is then the further advantage that you get positive feedback that the switch action has had the desired effect, as the switch will not move until the state change comes back from the device.
This is interesting insight into the use of join node. I think I confused matters by not making clear that the button I was referring to was a physical zigbee button and not a NR dashboard button.
There is an example describing this technique in the cookbook. https://cookbook.nodered.org/basic/join-streams
I use the pattern very often. An advantage over using context is that the data flow is obvious. With context variables it is easy to lose track of what is used where.
If it is a physical button then my ui-switch option obviously doesn't work