Sonoff RF Bridge. Strategies for receiving data

Here are two strategies for receiving payloads published by a Sonoff RF Bridge (flashed with Tasmota firmware).

Strategy 1: value_template

In this strategy, all sensors are subscribed to the same topic published by the RF Bridge. The topic's structure depends on how you defined it when you configured *your* RF Bridge. This example will use `tele/RF_Bridge/RESULT`. Change that to whatever you have set for your Bridge.

Because all sensors are subscribed to the same topic, a sensor will receive payloads intended for another sensor. When this happens, its value_template has to produce a valid state. If it doesn’t, Home Assistant will report the following warning message: “No matching key found for entity”. The sensor’s value_template must always returns a valid state.

For an MQTT Binary Sensor, the default for payload_on is ON and for payload_off it’s OFF (i.e. uppercase). On the other hand, the state of a binary_sensor can either be on or off (i.e. lowercase). Keeping this important distinction in mind, we can use it to construct a value_template that ensures the payload always matches something and never nothing.

In the example below, if the payload contains neither 2C8D0A or 2C8D0E, it reports the binary_sensor’s current state. In other words, no matter what it receives in the payload, the value_template always reports a valid state.

- platform: mqtt
  name: 'Bathroom Door'
  state_topic: 'tele/RF_Bridge/RESULT'
  value_template: >-
    {% if value_json.RfReceived.Data == '2C8D0A' %}
      {{'ON'}}
    {% elif value_json.RfReceived.Data == '2C8D0E' %}
      {{'OFF'}}
    {% else %}
      {{states('binary_sensor.bathroom_door') | upper}}
    {% endif %}
  device_class: door

If you have a sensor that does not report an off state then you can compensate by using the off_delay option.

In this example, Data=E5D30E indicates the motion sensor is on but there’s no command available to indicate when the sensor is off. I have set off_delay: 15 so the motion sensor will automatically set itself to off after 15 seconds.

- platform: mqtt
  name: 'Hallway Motion'
  state_topic: 'tele/RF_Bridge/RESULT'
  value_template: >-
    {% if value_json.RfReceived.Data == 'E5D30E' %}
      {{'ON'}}
    {% else %}
      {{states('binary_sensor.hallway_motion') | upper}}
    {% endif %}
  off_delay: 15
  device_class: motion

This strategy works well for a few sensors but does not scale well. There is a potential performance penalty because all sensors are subscribed to the same topic. If you have ten sensors, then every payload published by the RF Bridge will be evaluated by all ten sensors. In other words, each payload is processed ten times.


Strategy 2: Demultiplexer

Demultiplexing offers a performance advantage over the previous strategy. It uses an automation to separate (demultiplex) the RF bridge’s single topic into multiple topics, one per sensor. Each sensor is subscribed to its own topic and only receives payloads intended for it.

Unlike the previous strategy where, for ten sensors, each payload is processed ten times, this strategy processes each payload only twice. The payload is initially processed by the automation and then by the sensor.

To make this work, you have to configure Home Assistant to use the python_script component. Full instructions can be found in the documentation for the python_script integration. Here are the basic steps:

  1. Add python_script: to your configuration.yaml file.
  2. Create the following sub-directory: config/python_scripts
  3. Restart Home Assistant.

Create a new file in config/python_scripts called rfbridge_demux.py with the following contents:

d = { '2C8D0A':['sensor1','ON','true'],
      '2C8D0E':['sensor1','OFF','true'],
      'E5D30E':['sensor2','ON','false'],
      '30D8A0':['sensor3','ON','false']
    }

p = str(data.get('payload'))

if p is not None:
  if p in d.keys():
    service_data = {'topic':'home/{}'.format(d[p][0]), 'payload':'{}'.format(d[p][1]), 'qos':0, 'retain':'{}'.format(d[p][2])}
  else:
    service_data = {'topic':'home/unknown', 'payload':'{}'.format(p), 'qos':0, 'retain':'false'}
    logger.warning('<rfbridge_demux> Received unknown RF command: {}'.format(p))
  hass.services.call('mqtt', 'publish', service_data, False)

Obviously you will have to modify the dictionary (d) so it contains your RF bridge’s commands. The format of each item in the dictionary is straightforward:

'payload':['topic','state','retain']

Because we are using a python_script, you can add sensors to the dictionary without having to restart Home Assistant. The dictionary is designed so you can specify if the sensor’s topic should have its payloads retained or not.

  • Because the door sensor reports both of its states, the automation can use retain: true when publishing to the contact sensor’s topic. When Home Assistant restarts, it will re-subscribe to the contact sensor topic’s and receive its current (retained) state from the broker. :+1:

  • The other two sensors (motion sensor and button) don’t report their off state. We use the off_delay option to automatically reset them to off. However, this technique does not publish off to their respective MQTT topic (i.e. once set to on the topic will always show on). Therefore the automation should publish to their topics using retain: false. Otherwise,if using retain: true, when you restart Home Assistant, it would erroneously set these sensors to on. :-1:

Here’s the required automation. Don’t forget to change topic: to the topic you configured for your RF Bridge.

- alias: 'rfbridge_demultiplexer'
  trigger:
  - platform: mqtt
    topic: tele/RF_Bridge/RESULT
  action:
  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{trigger.payload_json.RfReceived.Data}}'

Configuring the binary sensors becomes an easy task. No value_template is needed.

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

  - platform: mqtt
    name: 'Hallway Motion'
    state_topic: 'home/sensor2'
    off_delay: 5
    device_class: motion

  - platform: mqtt
    name: 'Button1'
    state_topic: 'home/sensor3'
    off_delay: 1

NOTE

If you use Strategy 2 and have more than one RF Bridge, you can simply configure all of them to publish to the same topic. Alternatively, assign a unique topic to each one then, in automation.rfbridge_demultiplexer, create an MQTT Trigger for each topic.


EDIT

If you wish to use Node-Red to perform the task of demultiplexing (instead of the suggested python_script) a suitable function node is provided here.

EDIT

Minor revisions to the instructions for configuring the python_script integration.

EDIT

In the python_script, changed this:

p = data.get('payload')

to this:

p = str(data.get('payload'))

in order to accommodate to 0.118’s automatic type conversion where numeric strings are automatically converted to integers.

62 Likes

good job, thanks for sharing

Thanks a lot for this!

Thanks for the write up. The instructions are very clear but somehow I couldn’t get either one work at all. I maybe miss something my script.

Did you want help to fix it?

1 Like

Still haven’t got it work yet. Mostly copy and paste from your code, only change certain things to match with whatever I have. I preferred 2nd method as you recommended since it’s more efficiency
executions. I did reboot ha many times with no error on these scripts. They’re all show properly in HA screen but no state changes when device is open or closed. I was trying to troubleshoot these but I don’t see any error logging in the log file.
Thanks for your concern.

Yes, please. Can you help me troubleshot it? another thing my RF received data format code in decimal, Shoud I change to hex format.

I’ll need to see a sample of the payload produced by the RF Bridge, the automation, and at least one or two sensor configurations.

I found out that I have different topic tele/RFBridge/RESULT instead of tele/RF_Bridge/RESULT.
so I change topic in automation script but it still does not change state at all.

  • alias: ‘rfbridge_demultiplexer’
    trigger:
    • platform: mqtt
      topic: tele/RFBridge/RESULT
      action:
    • service: python_script.rfbridge_demux
      data_template:
      payload: ‘{{trigger.payload_json.RfReceived.Data}}’

I can see the automation script trigger evertime door sensor open/closed

rfbridge_demux.py
d = { ‘1230602’:[‘sensor1’,‘ON’,‘true’],
‘1230606’:[‘sensor1’,‘OFF’,‘true’],

Binary sensor:

  • platform: mqtt
    name: ‘Test Door’
    state_topic: ‘home/sensor1’
    device_class: door

Message in 433Mhz RF Bridge

here is my old working one.

  • platform: mqtt
    name: ‘Test Door’
    state_topic: ‘tele/RFBridge/RESULT’
    value_template: ‘{{value_json.RfReceived.Data}}’
    payload_on: ‘1230602’
    payload_off: ‘1230606’
    device_class: door
    qos: 1

I got it work now. I did copy rfbridge_demux.py again and modified the d part, I must change something which caused mess up on previous python_script.

I need help to write a script to reset device with 1 code instead of off_delay:xx

DY-SQ100B Water Leakage Detector

Here is my old reset script
Reset script
sequence:

  • service: mqtt.publish
    data:
    topic: “tele/RFBridge/RESULT”
    payload: “{“RfReceived”:{“Data”:“11700753off”}}”
    retain: “true”

Thanks,

Good work!

Why do you want to use an automation to set a binary_sensor to off when off_delay can do that for you?

I just want to inspect the water leak area before reset the device manually.

1 Like

@123
This is great solution. Thank you very much for creating and sharing it.
Have you got it in github? if yes, would you consider adding the custom_component json tracker:

A note for those that may make the same mistake i made. My rfbridge topic is sonoff/rfbridge. So
your automation trigger needs to reflect that. in my case:

- alias: 'rfbridge_demultiplexer'
  trigger:
  - platform: mqtt
    topic: tele/sonoff/rfbridge/RESULT

It may be obvious, but I missed it initially.

1 Like

That’s a good idea. All you would need to do is publish OFF (uppercase) to the sensor’s MQTT topic. Here’s an example of a script to do that:

#script:
  reset_sensor:
    alias: Reset sensor
    sequence:
      - service: mqtt.publish
        data:
          topic: home/sensor3
          payload: 'OFF'

2 Likes

No. I have no plans to update the python script. It’s presented here as an example and its contents, notably the dictionary, *have to be customized

I thought I had made that obvious when I said “Typically the topic will be like …” as opposed to saying “This is the topic …”. Nevertheless, you are the second person who overlooked to modify it so I will re-phrase the sentence to make it clearer that users must adapt the topic for their needs.

Once again thank you for your contribution.

Got it. Thanks again.

what’s happen if 2 or 3 sensors occur at exact same time, does the automation script process them all?

1 Like

The question of “What happens when two RF devices transmit at the same moment in time?” is a question best answered by the designer of the Tasmota firmware.

The RF Bridge publishes the RF events to its topic, based on the order it receives them. It’s the RF Bridge that has to handle the case of concurrent RF events.

The automation simply subscribes to the RF Bridge’s topic and processes the payloads in the order they are received.