Can a MQTT Binary Sensor retain it's status or do I need an Input_Boolean?

I have tried PowerRetain, SwitchRetain and SensorRetain and none seem to work.

I have also tried the recorder function:

recorder:
  include:
    entities:
      - binary_sensor.master_bedroom_window

Also tried

recorder:
  include:
    domains:
      - sensor

But again no luck :disappointed:

Will give boolean_inputs ago, but makes for a more messy setup.

Let me know if this is correct:

  • There is just one topic, tele/sonoffBridge/RESULT, representing the states of multiple sensors.
  • You use the contents of the payload to differentiate between the sensors. Effectively, the payload is used like a fingerprint to identify the sensor.

If all of the above is true then I don’t believe you can use retain to have the MQTT Broker store the state of each sensor. All sensors are represented by only one topic and only that single topic’s messages can be retained. In practice this means (at best) that at the moment Home Assistant reconnects to the Broker, it only has the state of the last sensor to have published something.

You’ll need another means to store the sensor’s state. I believe the value of an input_boolean survives a restart. It can be used (via automations) to store the binary_sensor’s state-changes and restore its state upon startup. It’s not pretty but that’s the current state of things (no pun intended).

1 Like

Yes I am just getting the RESULT bit ie

16:37:53 MQT: tele/sonoffBridge/RESULT = {“RfReceived”:{“Sync”:9510,“Low”:340,“High”:910,“Data”:“1234E7”,“RfKey”:“None”}}

or

16:38:01 MQT: tele/sonoffBridge/RESULT = {“RfReceived”:{“Sync”:9510,“Low”:340,“High”:910,“Data”:“1234E8”,“RfKey”:“None”}}

Etc and just using the “Data”
It doesn’t even retain the last value sent.

Not to worry I will setup some input_boolean’s

It’s also a shame the Door Class isn’t tri state instead of being just on / off as these sensors have a tamper code as well.
I will look into perhaps setting up a cover. Or I may just have a separate tamper sensor?

FWIW, my sensors publish on separate topics and use retain=true so their messages are retained by the Broker. Upon startup, HA gets the current state of all sensors (when it re-subscribes to all sensor topics). However, in your situation (with a single topic), it’s no longer worthwhile to explore why the last published message isn’t being retained.

Or I may just have a separate tamper sensor?

That’s what I’d do. For example, the climate component does not support the fan’s current state so I handle it using an MQTT Sensor.

  - platform: mqtt
    name: "HVAC Fan Status"
    icon: mdi:fan
    state_topic: "premise/home/thermostat/fanstatus"
    value_template:  >-
      {% set values = { '0':'Off',  '1':'On' } %}
      {{ values[value] if value in values.keys() else '?' }}

I have swapped it over to an input_boolean
Little bit messy but not too bad.

input_boolean:
  master_bedroom_window:

automation:
- alias: Window Open
  trigger:
    platform: mqtt
    topic: tele/sonoffBridge/RESULT
  condition:
    condition: template
    value_template: '{{ trigger.payload_json.RfReceived.Data == "1234EE" }}'
  action:
    service: homeassistant.turn_on
    entity_id: input_boolean.master_bedroom_window

- alias: Window Close
  trigger:
    platform: mqtt
    topic: tele/sonoffBridge/RESULT
  condition:
    condition: template
    value_template: '{{ trigger.payload_json.RfReceived.Data == "1234" }}'
  action:
    service: homeassistant.turn_off
    entity_id: input_boolean.master_bedroom_window

Just need to decide if to try a cover or install custom-ui to get the icons how I want them.

Shame you can’t use device_class: door on an input_boolean

I’ll throw out this idea as an alternative. I would continue to use a binary_sensor to represent the device’s state. It provides the best representation via its support using device_class.

The input_boolean would only serve to store the sensor’s state. In fact, it would be concealed from the UI using its hidden parameter. An automation, triggered upon Home Assistant’s startup, would use the input_boolean’s state to set the corresponding binary_sensor’s state.

There are other ideas in the following thread for storing values in some form of ‘global variable’ that can survive a restart.

1 Like

Here’s an interesting option.

That solution is an enormous kludge. Nevertheless, given the available options, it’s a good kludge. :slight_smile:

In nutshell, it’s splitting a single topic (representing many devices) into multiple topics (one per device). It allows you to subscribe to each unique sensor.

HA subscribes to the RF Bridge’s single topic, parses the received message into separate topics and publishes each one (with retain=true). Then it subscribes to each one of the topics it just published (where each topic now represents a unique sensor).

FWIW, if you are already running Node-Red, you can create a flow to do the same thing. It would subscribed to the RF Bridge, parse the incoming messages, and publish each sensor’s message in a separate topic (with retain=true). Now your binary_sensors can subscribe to unique topics whose messages are available when HA restarts. Nice.

I utilise NodeRED extensively for this purpose, taking an existing topic structure and republishing it either as different topic(s) or value, with retention if appropriate. You likely have to handle the reverse case too… In this case splitting a compound topic value into the individual topics and value. I don’t regard it as a kludge, just a transformation.

NodeRED is really good at this and also needn’t load HA in implementation, if on a separate cpu. It’s a great translator between automations.

I also don’t think using Node-Red to pre-process or transform values is a kluge. What I do think are kluges are the roundabout techniques people employ to solve a basic requirement, namely restoring entity states after a restart.

Call it ‘persistence’, or something else, but it’s missing in HA. A few entities, like input_boolean and others, are restored on startup using the values stored by Recorder. However, that’s a fraction of all entities so people use one bandaid solution or another to restore entity states.

As a benchmark, openHAB offers the ability to restore states and so does the HA system I’ve used for ten years (and it was invented in 1998). This feature is long overdue for Home Assistant. Having said that, I have seen a PR where the new JSON storage is being used to store an entitiy’s state.

Which broker are you using? I seem to remember that the embedded broker does not respect the retain flag, which may be why that solution did not work for you.

Thanks for the reply guys. I am using Mosquitto a my MQTT Broker.

I will stick to using an input_boolean in the back ground to keep it simpler than going back and forth with MQTT messages.

I will look at setting up a binary sensor for the front end to save having to use add on packages.

I will put a couple of feature requests in.

One to have more than two states for a device class.
To be able to use device classes on input_booleans.
For binary sensors to be persistent and survive a restart.

One to have more than two states for a device class.

For sensors, device_classes represent the magnitude of a given property like temperature, humidity, battery, etc.

For binary sensors, device_classes represent its two possible states. It can’t have three or more states because then it’s not a binary sensor.

To be able to use device classes on input_booleans.

If an input_boolean could be assigned a device_class of fan it could allow the UI to show icons of a moving or stopped fan (based on the state). That’s marginally better than what’s possible now (use customize to show a fan icon).

BTW, if you’re using an input_boolean to represent the state of something you cannot control (like a motion or contact sensor) then you’re using the wrong entity for the job. The UI will render a toggle switch which is misleading; the toggle switch suggests the end-user can control the state of the contact/motion sensor.

For binary sensors to be persistent and survive a restart.

This capability shouldn’t be limited to binary sensors. A persistence feature should be capable of storing the current value of all entities. You should have control over it so you can indicate which entities are included/excluded from the persistence feature. This sounds a lot like the existing Recorder component except it was never fully used for persistence (i.e. to restore states after a restart).

I got there in the end.
Still very long winded but it works.

This is setup as a package security.yaml

input_boolean:
  master_bedroom_window:
  master_bedroom_window_alarm:

automation:
##########
# Start of Master Bedroom Window
##########
- alias: master_bedroom_window_open
  trigger:
    platform: mqtt
    topic: tele/sonoffBridge/RESULT
  condition:
    condition: template
    value_template: '{{ trigger.payload_json.RfReceived.Data == "1234EE" }}'
  action:
    service: homeassistant.turn_on
    entity_id: input_boolean.master_bedroom_window

- alias: master_bedroom_window_close
  trigger:
    platform: mqtt
    topic: tele/sonoffBridge/RESULT
  condition:
    condition: template
    value_template: '{{ trigger.payload_json.RfReceived.Data == "1234E7" }}'
  action:
    service: homeassistant.turn_off
    entity_id: input_boolean.master_bedroom_window

- alias: master_bedroom_window_alarm
  trigger:
    platform: mqtt
    topic: tele/sonoffBridge/RESULT
  condition:
    condition: template
    value_template: '{{ trigger.payload_json.RfReceived.Data == "1234EB" }}'
  action:
    service: homeassistant.turn_on
    entity_id: input_boolean.master_bedroom_window_alarm


binary_sensor:
  - platform: template
    sensors:
      master_bedroom_window:
        friendly_name: "Master Bedroom Window"
        device_class: window
        value_template: >-
          {{ is_state('input_boolean.master_bedroom_window', 'on') }}

      master_bedroom_window_alarm:
        friendly_name: "Master Bedroom Window Alarm"
        device_class: problem
        value_template: >-
          {{ is_state('input_boolean.master_bedroom_window_alarm', 'on') }}

The Yellow Window Open and Problem symbol are the two binary_sensor’s

Thanks wills106!
This worked like magic for me.
The only problem is that after updating HA to 0.87.0, the sensor wouldn’t change state no matter what I try.

After few trials and errors, I realized that the mqtt topic had to be in double quotes for the automation to work again:

platform: mqtt
topic: "tele/sonoffBridge/RESULT"

Hi there ! Just a little update to refresh things up syntax-wise on this super helpful topic. On Hassio 0.94.3.

In configuration.yaml I have :

# Input Booleans
input_boolean:
  cave_door:
  garage_door:

# Binary Sensors
  - platform: template
    sensors:
      cave_door:
        friendly_name: "Cave Door"
        device_class: door
        value_template: >-
          {{ is_state('input_boolean.cave_door', 'on') }}

  - platform: template
    sensors:
      garage_door:
        friendly_name: "Garage Door"
        device_class: garage_door
        value_template: >-
          {{ is_state('input_boolean.garage_door', 'on') }}

Then in automations.yaml (as I have automation: !include automations.yaml entry in my configuration.yaml)

  - alias: cave_door_open
    trigger:
      platform: mqtt
      topic: rfbridge/tele/RESULT
    condition:
      condition: template
      value_template: '{{ trigger.payload_json.RfReceived.Data == "31D20A" }}'
    action:
      service: homeassistant.turn_on
      entity_id: input_boolean.cave_door

  - alias: cave_door_close
    trigger:
      platform: mqtt
      topic: rfbridge/tele/RESULT
    condition:
      condition: template
      value_template: '{{ trigger.payload_json.RfReceived.Data == "31D20E" }}'
    action:
      service: homeassistant.turn_off
      entity_id: input_boolean.cave_door

  - alias: garage_door_open
    trigger:
      platform: mqtt
      topic: rfbridge/tele/RESULT
    condition:
      condition: template
      value_template: '{{ trigger.payload_json.RfReceived.Data == "32BB0A" }}'
    action:
      service: homeassistant.turn_on
      entity_id: input_boolean.garage_door

  - alias: garage_door_close
    trigger:
      platform: mqtt
      topic: rfbridge/tele/RESULT
    condition:
      condition: template
      value_template: '{{ trigger.payload_json.RfReceived.Data == "32BB0E" }}'
    action:
      service: homeassistant.turn_off
      entity_id: input_boolean.garage_door

It is working absolutely great ! Thanks guys ! I am sure this have helped tons of RF Bridge users.

Although the solution I offered many months ago does work, I would now suggest a completely different one. It’s simpler to implement, easier to manage, and doesn’t require the use of input_booleans.

I recommend Strategy #2 in this post: Sonoff RF Bridge. Strategies for receiving data. It uses the concept of demultiplexing (demux).

The solution consists of:

  • One simple automation
  • One simple python_script

The configuration of each MQTT Binary Sensor is greatly simplified. It doesn’t even need a value_template.

For example, this is how simple they become when using Strategy #2:

  - platform: mqtt
    name: 'Cave Door'
    state_topic: 'home/sensor1'
    device_class: door

  - platform: mqtt
    name: 'Garage Door'
    state_topic: 'home/sensor2'
    device_class: garage_door

The only work you have to perform is configuring the JSON dictionary within the python_script (see the linked post for complete instructions).

For example, this is how it would be defined for @Lefuneste’s two binary_sensors:

d = { '31D20A':['sensor1','ON','true'],
      '31D20E':['sensor1','OFF','true'],
      '32BB0A':['sensor2','ON','true'],
      '32BB0E':['sensor2','OFF','true']
    }

The true you see there means the payload (ON or OFF) is published as a retained message. That means the binary_sensor’s state is stored by the MQTT broker so when Home Assistant restarts, it acquires the sensor’s latest state from the broker.

Adding another binary_sensor becomes child’s play:

Step 1: Define it.

  - platform: mqtt
    name: 'Kitchen Window'
    state_topic: 'home/sensor3'
    device_class: window

Step 2: Append its RF codes to the JSON dictionary in the python_script.

d = { '31D20A':['sensor1','ON','true'],
      '31D20E':['sensor1','OFF','true'],
      '32BB0A':['sensor2','ON','true'],
      '32BB0E':['sensor2','OFF','true'],
      '36DE0A':['sensor3','ON','true'],
      '36DE0E':['sensor3','OFF','true']
    }

Step 3: Restart Home Assistant.

Thanks @123 I will have a look into this method when I get chance. As I have quite a few new RF devices to setup.
Should help to clean it up alot!

Yeah Many thanks for the update. I’ll check it too !

Ok I have implemented this scripted solution and it seems to work just fine as well.