MQTT, Binary sensors and unexpected states

I have some 433MHz door and window sensors all connected to a Tasmotized Sonoff RF Bridge. These sensors all work perfectly and send a message when open and a different one when closed. They are all configured as shown below.

My question is regarding their state when restarting HA. As I understand it they should all return a state of ‘unavailable’ but mine all return ‘Closed’. am I missing something that explains this?

And:

The reason I discovered that my sensors were apparently behaving unexpectedly was because I asked in another post how others managed the fact that these sensors cannot be forced to retain their state following a restart. There must surely be a way around this, how else would people use them as the basis of alarm systems? The only way I can think of is the horrible kludge of saving the binary sensor state into an input boolean every time it changes. Again, am I missing something?

binary_sensor:
  - platform: mqtt
    name: "Door1"
    state_topic: "tele/sonoff_rf01/RESULT"
    value_template: '{{value_json.RfReceived.Data}}'
    payload_on: "AC860A"
    payload_off: "AC860B"
    device_class: Door
    qos: 1
    retain: true

and the actual MQTT message is in the form

{"RfReceived":{"Sync":14060,"Low":460,"High":1370,"Data":"AC860A","RfKey":"None"}}

3 Likes

You need to define the availability topic and payload (and send the corresponding message) for the state to be noted as unavailable

This is normally done be setting the retain flag on the state messages. The broker then retains the message in its database and sends it to all clients that subsequently subscribe to the topic. I don’t have tasmota, so can’t tell you how, but I’m sure it allows you to set the retain flag.

In order to retain the state of these devices, you’ll need to republish the data into a device specific topic.

alias: Door1 433 Codes
trigger:
  - platform: mqtt
    topic: "tele/sonoff_rf01/RESULT"
condition:
  - condition: template
    value_template: "{{ trigger.payload in ('AC860A','AC860B') }}"
action:
  - service: mqtt.publish
    data_template:
        topic: "433/Door1"
        payload: "{%- if trigger.payload == 'AC860A' -%}ON{%- else -%}OFF{%- endif %-}"
        retain: True

Then set your binary_sensor up like this:

binary_sensor:
  - platform: mqtt
    name: "Door1"
    state_topic: "433/Door1"
    device_class: Door

The availability topic mentioned by @gpbenton doesn’t work as expected in this case because the 433Mhz devices connect THROUGH the Sonoff RF Bridge and the availability topic would only tell you if the bridge is online, not the most recent status from that particular 433Mhz device.

The downside to this setup, and any device that doesn’t retain it’s own state, is that if the state changes while HASS is down, HASS won’t know about it until the state changes again. So… if the door is open and then you stop HASS and close the door, when you start HASS again, it’ll still see the door as open.

1 Like

Brilliant! Thank you, I’ll give that a try.


Yes I guess there can be no perfect solution given the sensors are entirely passive and respond to the outside world rather than actually sensing it. But your solution is a big improvement. Thanks again.

1 Like

That is really the point of the unavailable state - to indicate that the status of the sensor is unavailable, possibly due to a hub going down.

Yes… but the Sonoff RF Bridge (or any other RF/IR listening device like the Broadlink devices, Xiaomi IR transceivers, or the “roll your own” ESP8266 based sensors like the OpenMQTTGateway), is a device that listens for other devices. And those other devices don’t connect through MQTT nor do they announce their availability to the Sonoff RF Bridge. So the availability topic would tell you if the Sonoff RF bridge was available. But it wouldn’t tell you if a particular RF device was available. And since each RF device’s trigger is simply seen as a different code to the Sonoff RF bridge, there’s no way to know the availability of any particular RF device without adding data retention (as the MQTT republishing automation I showed above does).

So, while the availability topic can indicate whether RF codes can be received at all, it wouldn’t indicate the previous state of any particular RF device.

For a more complete sensor, each RF device, using the binary_sensor YAML I showed above, could include the availability topic of the RF Bridge. This way, if the RF bridge did go offline, those sensors would show as unavailable as well. But it wouldn’t handle the OPs case of wanting to either see “unavailable” on this particular sensor or the last known state whenever HASS is restarted. When HASS is restarted the availability of the RF Bridge would be “online”, but HASS would have no idea what the state for that particular device was.

As I mentioned, because the RF devices themselves cannot generally handle a state request, this setup isn’t 100% perfect. There CAN be times when the state in HASS/MQTT is incorrect regarding the RF device. These cases include: if the RF Bridge is stopped/restarting when the RF device transmits a new state, if HASS is stopped/restarting when the RF Bridge publishes a new state (though this case could be corrected by moving the MQTT republishing to a process outside of HASS), or if the transmission from the RF Device was not received by the RF Bridge for whatever reason (interference, too many transmissions at once, device out of range, etc).

Dealing with these RF Devices is a different beast entirely because, essentially, they always run in what HASS calls “assumed state” mode. And, with “assumed state” comes “assumed availability”.

Just to clarify I don’t want the ‘unavailable’ state, It was suggested elsewhere that I should be getting it.

I’m just about to try your suggestions but with all the restarts I’m going to need, I could be some time!! :slight_smile:

I tried this and the condition is not working. I decide that was because payload contains several elements so I tried

  - condition: template
    value_template: "{{ trigger.value_json.RfReceived.Data in ('DC5F0A','DC5F0E') }}"

but that didn’t work either.

I tried removing the condition altogether and it always published ‘OFF’ which also implies that trigger.payload or trigger.value_json.RfReceived.Data are not the correct thing to be using.

Do you have any suggestions?

Ah, I forgot you were using json, and not the entire payload. You almost had it. It’s:

trigger.json_payload.RfReceived.Data

ooohh… so close!
Thanks, I’ll give it a try this evening.

1 Like

@swiftlyfalling
I’m really sorry but this still doesn’t work I’m afraid. I think there is still something wrong with the value_template.

I set up a persistent notification using {{ states('trigger.json_payload.RfReceived.Data') }} and it returned ‘Unknown’.


The payload from the sensor is in the form:
{"RfReceived":{"Sync":14020,"Low":480,"High":1350,"Data":"11D60E","RfKey":"None"}}


My automation to republish the MQTT is:

  - id: door_republish_mqtt
    alias: Door republish mqtt
    trigger:
      - platform: mqtt
        topic: "tele/sonoff_rf01/RESULT"
    condition:
      - condition: template
        value_template: "{{ trigger.json_payload.RfReceived.Data in ('11D60A','11D60E') }}"
    action:
      - service: mqtt.publish
        data_template:
          topic: "433/door"
          payload: "{%- if trigger.json_payload.RfReceived.Data == '11D60E'-%}ON{%- else -%}OFF{%- endif -%}"
          retain: True

And my sensor is defined as:

  - platform: mqtt
    name: "Front Door"
    state_topic: "433/fdoor"
    device_class: Door

That persistent notification won’t work because states() can’t be used in that particular case.

However, I think the issue is the state_topic line of your sensor.

In the action you are publishing to 433/door. But your state_topic is 433/fdoor … with the “f” in there.

@swiftlyfalling

I didn’t know this…

and the fdoor is a typo but only in this post. I copied and pasted my config and then edited it here to make it more generic. Probably not the best decision in hindsight.

I’ll keep playing with it but if you have any further suggestions I’d be grateful.

Ahhh… my mistake. One of the problems with HASS is not being able to easily test anything without restarting HASS 27,000,000 times.

All the places where I said “json_payload”… it should be “payload_json”. :slight_smile:

It’s not just HASS, I use hassio and it takes forever to restart. It really ca put you off changing anything especially if you want to experiment. And typos are very costly! I’m showing my age here but it reminds me of the old days when we had to submit a job just to compile our programs let alone test them and wait for the next day to see the output!!

Anyway, thanks I really appreciate your help. Give me a day or two and I might have tried this again :slight_smile:

1 Like

Hi did you manage in the end? Trying to do exactly what you did, but confused on which is the correct code in the end …

Yes I did :slight_smile:

I have automations like this:

  - alias: Front Door republish mqtt
    initial_state: on
    trigger:
      - platform: mqtt
        topic: "tele/sonoff_rf01/RESULT"
    condition:
      - condition: template
        value_template: "{{ trigger.payload_json.RfReceived.Data in ('12345A','12345E') }}"
    action:
      - service: mqtt.publish
        data_template:
          topic: "433/front_door"
          payload: "{%- if trigger.payload_json.RfReceived.Data == '12345A' -%}ON{%- else -%}OFF{%- endif -%}"
          retain: True
2 Likes

This thread is exactly what I was looking for. I noticed the same thing because I set my house up with 433MHz door and window sensors and every time I opened up all the windows in the house and did a home assistant restart I’d lose the states of the windows, they’d all return to “Closed” even though they were really open. @swiftlyfalling thank you so much for the MQTT automation suggestion, that makes this solution work VERY well!

1 Like

@klogg, so I just realized that the 433 door/window sensors I’m using have a low battery code as well as opened/closed. Now I’m trying to figure out how to integrate that code with all my door/window sensor MQTT setups that I got from this thread.

It doesn’t seem to work out nicely since there are now three codes. Using the if/else/endif statement doesn’t make sense and I don’t think that we can set “low battery” for one of the states of door’s binary sensor. It would be nice to set an attribute but I can’t seem to wrap my head around how to do that with the MQTT automation yaml.

Any ideas?

Have you seen this thread?