I would like to get state_topic working on my switch, and would love some feedback.
I have an MQTT switch that sends messages to my ESP32 Arduino board to turn irrigation valves on and off – this works fine. I would like to make it a closed loop system: have the switch receive a message that the action has been carried out, and only then would the HA dashboard show the change in state.
I have set it up so that the ESP32 sends out the MQTT confirmation when it receives the command – this also works fine. However, the HA dashboard does not react to the message at all. Here’s the part of my config:
I’ve tried with and without the state_on / _off lines, and have restarted HA, but no luck. I’m not even sure where to look. Does anyone have tips on how to debug this?
Yes, clear. I had it in there as I was testing ON/OFF instead of the payload.
That doesn’t seem to change whether state_topic accepts json without a template. I’ve tried a few variants, including leaving out state_on/off, but it does not make a difference.
It is a shame, but seems my original conclusion is correct: payload_ accepts json without a template, but state_ does not.
I think you are still not clear about how MQTT template switch works.
It uses state topic to get state of the switch and command topic to control it.
There are 2 different cases
You receive garden/state RUN or garden/state IDLE when your switch is on or off and you send garden/command RUN or garden/command IDLE to turn your switch on or off.
You receive garden/state RUN or garden/state IDLE when your switch is on or off and you send garden/command TURN_ON or garden/command TURN_OFF to turn your switch on or off.
As you can see, the difference is in what strings you need to look for when analysing state topic and what you need to send to command topic. These strings are called payloads.
In the first case payloads for both topics are the same. However, you need to specify payload_on and payload_off as they are different from the default ones (ON/OFF):
payload_on: RUN
payload_off: IDLE
In the second case in addition to payload_xxx you need to define state_xxx as payload to turn your switch (TURN_ON ) is different from the payload that represents the switch’s on state in the state topic (RUN):
payload_on: TURN_ON
payload_off: TURN_OFF
state_on: RUN
payload_off: IDLE
And you need to define how to extract your payload from incoming messages in state topic as it’s JSON, not a simple string. So you should have:
value_template: {{ value_json['value'] }}
The bottom line is: payload_xxx and state_xxx are strings (so they cannot acccept anything) and these strings are used to match with the result of value_template.
Thanks, that is useful – it may be that I will need to learn how to use the templates and I will then use your explanation. Up until now, I have been resisting templates, as I am already learning too many things at once and want to limit the complexity.
My point was that I don’t use a value_template at all today. Nonetheless, payload_on: ‘{“valve”: “In1”, “value”: 1}’ works fine. Also, state_on: ‘ON’ works fine.
My point was not about how templates work. I was saying that I find it a shame that state_on requires a value_template while payload_on doesn’t. In any case, my solution of sending both messages does work without using a template.
Could you post here your configs illustrating what you did and what’s “fine”? Especially with state_on.
I can only re-iterate that you need to take your time learning the docs and idea behind it.
If you post your config, I’ll explain you how to use state_xx with or without templates as it’s not necessary (value_template is an optional variable).
like garden/state {“valve”:“In1”,“value”:1}?
4 question:
why do you need JSON here?
have you changed message format your device posts?
have you tried using a different key instead of value?
do I get it right that your last config does not show your device’s state?
tom is right (and the docs say that) - you only need state_xx if your state payload is not the same as your command payload. In your case it’s enough to define only payload_xx - have you tried to remove state_xx?
I don’t absolutely need json, it would make my program simpler. As I wrote, I have found a workaround.
I have not changed anything except what I have shown.
Yes, no json works for state
4.yes
I think you and Tom are missing the point. The question is whether state reads json or not, not whether it can be read. Documentation or no, I don’t believe state can read json without a template.
None of those payloads are JSON. They are strings that look like JSON.
Your initial aim was for closed loop control.
What I am trying to get through to you is you already had closed loop control when your command and state payloads were the same. The state messages were taken from the payload messages. There is no need to define state_on, or state_off in this case which is why it would not work for you unless you changed them to be different from the payload messages.
then you don’t need to declare state_xx as you send default values, try removing it in v1 and I bet it will still work as expected.
So you changed your config and it now expects {"valve": "In1", "value": 1} instead of ON in the state topic but you haven’t changed what your device publishes? Then your MQTT switch won’t be able to match ON (what you’re still publishing) with {"valve": "In1", "value": 1} (what you instructed it to look for in the state topic) and HA won’t display your device’s state correctly. And it should generate No matching payload in HA logs for that reason, too.
In this situation you have to change code of your device so instead of ON it sends {"valve": "In1", "value": 1}.
Ok. Could you explain as what exactly does"state reads json" mean?
I’m not sure what you mean by “you already had closed loop control when your command and state payloads were the same.” There would need to be a response from my irrigation controller for me to be sure that the command from HA was received and implemented. How do you think that has happened?
I think your point about “None of those payloads are JSON. They are strings that look like JSON.” was indeed my confusion. It was not “reading json” in payload_on, it was simply sending a text string that looked like json. That is what had me confused, as it seemed to use json in one case and not the other.
So you changed your config and it now expects {"valve": "In1", "value": 1} instead of ON in the state topic but you haven’t changed what your device publishes?
Apologies, that wasn’t precise enough. Yes, I also changed what the device publishes.
Could you explain as what exactly does"state reads json" mean?
Again, leaving aside the point the I probably need to learn to use a template, what I mean is that when I send ON/OFF to the state_topic it reacts. When I send ‘{“valve”: “In1”, “value”: 1}’ it does not. Actually, I think Tom’s point here is behind my misunderstanding: it was not “reading json” in payload_on, it was simply sending a text string that looked like json. That is what had me confused, as it seemed to use json in one case and not the other; rather, it seems it will not “use” json without the template.
When the payloads for command and state are the same ( as you had them originally) you don’t need to specify state_on and state_off. It uses payload_on and payload_off by default. It’s right there in black and white in the document I linked to above.
state_on
(string)(Optional)
The payload that represents the on state. Used when value that represents on state in the state_topic is different from value that should be sent to the command_topic to turn the device on .