Rtl_433 - binary sensors with "last seen" and "delay off" without using automation

Hi, I want to share an alternative (and hope simpler) approach to handle rtl_433 generated messages, mapping them to HA binary sensors, keeping track of the time the sensor was last seen (which is different than the last changed/last updated attribute of HA) and simulating they stay on for a while before turning off back again.

In my specific use case, I have a legacy alarm system made up of movement/door/window sensors whose triggers I need to bring into HA through rtl_433, but also kepping if possible a data structure consistent with the other Zigbee-based sensors that I have.

In most of the posts I’ve read on the topic, the approach most commonly adopted rely on a demultiplexer automation which triggers on the mqtt messages generated by rtl_433, publish a MQTT message to a more structured topic which is eventually mapped to a HA sensor configured with platform: mqtt (e.g. MQTT - topic - help - #6 by 123). Others used also template-based sensor. All of this worked just fine but at least in my environement it was sometimes generating some abnormal behavior.

I tried then to do everything within the sensor’s configuration, thus avoid the automation piece if unnecessary and ended up with the solution below.
My devices are generating a message when triggering (actually multiple messages since they transmit the same content multiple times in the radio network) which I can map to a HA sensor based on the combination of an “id” and “cmd” fields. Of course yours can behave differently.

First of all, I configured rtl_433 with this settings:

output mqtt://core-mosquitto:1883,user=<user>,pass=<password>,retain=1,events=rtl_433[/id]
report_meta time:iso

So to have events posted in topics like rtl_433/<id>, containing in the payload both “cmd” and an iso formatted timestamp.
“retain” is also used so when HA is restarted, the sensor does not shows up as unknown but gets back the latest value before the restart.

Then I configured each sensor with this settings:

mqtt:
  binary_sensor:
    - name: pir_first_floor_occupancy
      unique_id: binary_sensor.pir_first_floor_occupancy
      device_class: motion
      state_topic: "rtl_433/<id>"
      value_template: "{%-if (as_timestamp(now())-as_timestamp(value_json.time) < 5) %}{{value_json.cmd }}{%-else%}OFF{%-endif%}"
      payload_on: "<cmd>"
      off_delay: 90
      json_attributes_topic: "rtl_433/<id>"
      json_attributes_template: "{{ {'last_seen': value_json.time} | tojson }}"

Where of course <id> and <cmd> are just placeholders.
Some considerations:

  • state_topic maps the sensor to the topic which contains the “id” of the device which triggered. “cmd” is evaluated at a later stage (see below)
  • value_template pre-process the payload, checks if the timetamp of the last time the device triggered took place within the last 5 seconds and if so returns the “cmd”, otherwise returns “OFF”. This logic prevents the sensor to become “on” (and hence the alarm to trigger) when HA restarts (since the message is retained on the bus, upon restart, it could be seen as a state change)
  • payload_on is the expected “cmd”, this is compared with the output of value_template. I used this logic since I have different devices with the same “id” but different “cmd”.
  • off_delay: automatically handles the state of the device, keeping it “on” for 90 seconds and then turning it back off. In this way it is consistent with my zigbee-based sensors. This also helps “debouncing” the sensor and preventing the alarm automation to trigger multiple times since the same message is transmitted a few times by the device upon a trigger event
  • json_attributes_topic / json_attributes_template: gets the iso-formatted “time” field from the mqtt message and create an attribute called “last_seen”. In this way, regardless of the HA last changed / last updated attribute, which is updated e.g. when HA restarts, the “last_seen” attribute always stores the last time the device actually triggered. Finally, in this way, my automation which checks if a sensor is no more reachable (e.g. because run out of battery), can rely on this attribute and is consistent (and formatted in the same way) of my other zibgee sensors

Hope it can help
Thanks