Sonoff RF Bridge. Strategies for receiving data

It’s driving me nuts…

I’ve been working hard to adapt your second strategy (demultiplexer) to my Sonoff RF Bridge to no avail.

My Bridge is flashed with Espurna firm, direct hack option. https://github.com/xoseperez/espurna/wiki/Hardware-Itead-Sonoff-RF-Bridge---Direct-Hack It’s working great

Referring to sensors, Espurna can publish MQTT https://github.com/xoseperez/espurna/wiki/RFBRIDGE in two ways.

A- A payload string Ex: “C001016118005699BB”
B- A json payload string like:

{ "rfin": "C001016118005699BB", "time": "2020-04-10 11:44:44", "mac": "C4:5F:77:A2:87:C8", "host": "Sonoff-RF-Bridge-1", "ip": "10.12.16.130", "id": 8 }

I prefer option A, which reduces RF traffic.

In HA I’ve set a RF-Bridge sensor: “sensor.espurna_rf_bridge_1” which takes state from incoming RF by using value_template:

value_template: > {% if not value %} "No data" {% endif %} {{ value[-6:] }}

Because only last 6 values don’t change for each state device. Rest are timing values.

I can check sensor.espurna_rf_bridge_1 changing state: 5699BB 749D55 and so on.

Now, back to problem. Second strategy set. I can see automation is triggered when MQTT is incoming or when sensor.espurna_rf_bridge_1 state changed. Both work. No problem to trigger rfbridge_demux.py. If I mod python script from p = data.get(‘payload’) to p= 5699BB, PIR sensor is triggered. So, rfbridge_demux.py is working too.

To tell in short, what I can’t achieve is an automation, action, data_template to parse data to rfbridge_demux.py. In spite I’m not skilled in Jinja nor python, I’ve tried playing handreds of no working femplates, including json templates, Ex:

{% set temp_json = { "data": states('sensor.espurna_rf_bridge_1') } %}

But I really can´t get it.

I tried with B too, setting Espurna to publish json format and using it to parse rfin 3 last bytes to the script but I couldn’t get a data_template either.

Please, can somebody help me to parse right value to rfbridge_demux.py?

I assume you’re having hard time changing rfbridge_demultiplexer automation.
If you’re using payload string (your option A), you need to extract data from payload, that’s it:

payload: '{{ trigger.payload[-6:] }}'

Hi, thanks.
No, it doesn’t work. I just tried.
I think "data.get(‘payload’) should expect a json to extract “data” value. But no python skill at all.

what does that mean?
by the way, quotes around the template are not single ones - use single/double quotes.

Sorry. My fault.
I mean I tried your suggested data_template and it didn’t work.
Beside that, if you look into rfbridge_demux.py code, you’ll find:
p = data.get(‘payload’)
Which I guess is to extract value data from json payload parsed to rfbridge_demux.py, but I’m not sure at all.

I think you don’t understand me. There is no such thing “it does not work”.
Imagine yourself seeing a doctor because you’re unwell. He asks you various question to understand what’s the reason but all you say to him is “I AM UNWELL, PLEASE HELP ME”.
Please read this before we carry on.

It gets a payload variable that HA put into special data dictionary used to pass service data to python_scripts. That payload variable is formed when HA finds payload: blah inside service data (data or data_template).

I’m really grateful to you for helping me
I know my English isn’t as good as I would like.
I thought I was understanding you and doing my best summarizing the problem.
Please, let me try again.

Running Hassio. Docker. DSM ( Synology)
HA 0.108.2

arch x86_64
dev false
docker true
hassio true
os_name Linux
os_version 4.4.59+
python_version 3.7.7
timezone Europe/Madrid
version 0.108.2
virtualenv false

Configuration:

From my automations.yaml

- id: '1586546570081'
  alias: RF Topic MQTT desmultiplexación
  description: ''
  trigger:
  - platform: mqtt
    topic: Piso/Sonoff-RF-Bridge-1/rfin
  condition: []
  action:
  - data:
      data_template:
        payload: '{{ trigger.payload[-6:] }}'
    service: python_script.rfbridge_demux

rfbridge_demux.py

d = { '8349AA':['PIR_hacia_entrada','ON','false']
    }

p = 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)

From binary_sensors.yaml

  - platform: mqtt
    name: "PIR_hacia_entrada"
    state_topic: "home/PIR_hacia_entrada"
    device_class: motion
    off_delay: 5

My Try:

I Published MQTT 8888888888349AA on topic: Piso/Sonoff-RF-Bridge-1/rfin

From UI Reg:

16:35:29 ESPURNA RF-Bridge-1-C44F33A287C4 RFIN changed to unknown
16:35:27 RF Topic MQTT desmultiplexación has been triggered
16:34:48 RF Topic MQTT desmultiplexación turned off

No Error on log

Please, tell me if you need more info.

Your RF Topic MQTT desmultiplexación is incorrect: you should not use data_template inside data.
Here’s the right one

- id: '1586546570081'
  alias: RF Topic MQTT desmultiplexación
  description: ''
  trigger:
  - platform: mqtt
    topic: Piso/Sonoff-RF-Bridge-1/rfin
  condition: []
  action:
  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{ trigger.payload[-6:] }}'
1 Like

Good Lord!
Kudos to AhmadK!
It´s working!

18:00:39 PIR_hacia_cocina cleared (no motion detected)
18:00:35 ESPURNA RF-Bridge-1-C44F33A287C4 RFIN changed to unknown
18:00:33 PIR_hacia_cocina detected motion
18:00:33 RF Topic MQTT desmultiplexación has been triggered
18:00:25 RF Topic MQTT desmultiplexación turned off

Five days trying hard all sort of data_templates and never realized Jinja was adding -data by itself!

Thanks, thanks, thanks a lot!

?

Sorry. I’m HA newbie.
If I set action by User UI, it changed on YAML edit mode. Added data.action YAML action

Ex: Two actions per picture. First as YAML mode. Second picture seen as User UI.
I did them on User UI. On YAML mode, data: was added.

For future reference, it’s not “Jinja” that’s adding anything. It’s the editor in the UI.

You friends and “Corona” home time are teaching us intense mode.
Keep on jour job, please.

Congratulations!
next time please post your config instead of explaining what you did. also, post code and not images.

I have played around with Strategy 2 which works well as many others have said. However, I was wondering if it might be possible to modify the Python script to publish sensor values rather than binary values which would significantly reduce the number of entities needed for multi-button remotes.

I currently have this:

d = { '9D4899':['level-1','ON','false'],
      'DAC012':['leak-g1','ON','false'],
      'AAAAAA':['battery-g1','ON','false'],
      'C2C112':['leak-g2','ON','false'],
      'BBBBBB':['battery-g2','ON','false'],
      '88C212':['leak-g3','ON','false'],
      '88C22D':['battery-g3','ON','false'],
      '25C112':['leak-g4','ON','false'],
      '25C12D':['battery-g4','ON','false'],
      'BB5DFD':['doorbell-1','ON','false'],
      'EBA782':['doorbell-2','ON','false'],
      '7DE426':['doorswitch-1','ON','false'],
      'ED600E':['motion-1','ON','false'],
      'CEF526':['motion-2','ON','false'],
      'DF9BE1':['remote-1a','ON','false'],
      'DF9BE2':['remote-1b','ON','false'],
      'DF9BE4':['remote-1c','ON','false'],
      'DF9BE8':['remote-1d','ON','false'],      
      'A051B4':['remote-2a','ON','false'],
      'A051B2':['remote-2b','ON','false'],
      'A051B1':['remote-2c','ON','false'],
      'A051B8':['remote-2d','ON','false'],       
      'E140C8':['remote-3a','ON','false'],
      'E140C4':['remote-3b','ON','false'],
      'E140C2':['remote-3c','ON','false'],
      'E140C1':['remote-3d','ON','false'], 
      'E140CC':['remote-3e','ON','false'],
      'E140C9':['remote-3f','ON','false'],
      'E140C5':['remote-3g','ON','false'],
      'E140C3':['remote-3h','ON','false']      
    }

And I would like to achieve something like the following:

      'E140C8':['remote-3','Button A','false'],
      'E140C4':['remote-3','Button B','false'],
      'E140C2':['remote-3','Button C','false'],
      'E140C1':['remote-3','Button D','false'], 
      'E140CC':['remote-3','Button E','false'],
      'E140C9':['remote-3','Button F','false'],
      'E140C5':['remote-3','Button G','false'],
      'E140C3':['remote-3','Button H','false']

My current code to achieve this in a single sensor template is this:

- platform: mqtt
  name: 'Remote3'     # Sonoff 8 button white Remote
  state_topic: 'tele/RFbridge01/RESULT'
  expire_after: 2
  value_template: >-
    {% if   value_json.RfReceived.Data == 'E140C8' %} Button A
    {% elif value_json.RfReceived.Data == 'E140C4' %} Button B
    {% elif value_json.RfReceived.Data == 'E140C2' %} Button C
    {% elif value_json.RfReceived.Data == 'E140C1' %} Button D
    {% elif value_json.RfReceived.Data == 'E140CC' %} Button E
    {% elif value_json.RfReceived.Data == 'E140C9' %} Button F
    {% elif value_json.RfReceived.Data == 'E140C5' %} Button G
    {% elif value_json.RfReceived.Data == 'E140C3' %} Button H
    {% else %} Unknown
    {% endif %}

I currently use two 4-button remote and an 8-button remote, a solution like this would reduce the number of entities required from 16 to 3.

Cheers!

Perhaps I have misunderstood your request but all you need to do is modify the dictionary’s contents. For example, change this:

      'DF9BE1':['remote-1a','ON','false'],
      'DF9BE2':['remote-1b','ON','false'],
      'DF9BE4':['remote-1c','ON','false'],
      'DF9BE8':['remote-1d','ON','false'],

to this:

      'DF9BE1':['remote-1','Button A','false'],
      'DF9BE2':['remote-1','Button B','false'],
      'DF9BE4':['remote-1','Button C','false'],
      'DF9BE8':['remote-1','Button D','false'],

Then just modify your existing MQTT Sensor to listen to the appropriate topic (which I assume is home/remote1) and remove the existing value_template.

- platform: mqtt
  name: 'Remote1'
  state_topic: 'home/remote1'
  expire_after: 2

You are quite right - this does work and cuts the YAML down immensely. Many thanks!

hi all,

im using this python script since many time, but i don’t know from how many time i have this errror:

2020-05-07 15:42:52 INFO (MainThread) [homeassistant.components.automation] Executing [SYS] DEMUX RF Sensor
2020-05-07 15:42:52 INFO (MainThread) [homeassistant.components.automation] [SYS] DEMUX RF Sensor: Running script
2020-05-07 15:42:52 INFO (MainThread) [homeassistant.components.automation] [SYS] DEMUX RF Sensor: Executing step call service
2020-05-07 15:42:52 ERROR (MainThread) [homeassistant.components.automation] [SYS] DEMUX RF Sensor: Error executing script. Unexpected error for call_service at pos 1: Error rendering data template: UndefinedError: 'dict object' has no attribute 'RfReceived'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 222, in async_render
    return compiled.render(kwargs).strip()
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 1, in top-level template code
  File "/usr/local/lib/python3.7/site-packages/jinja2/sandbox.py", line 407, in getattr
    value = getattr(obj, attribute)
jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'RfReceived'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 132, in async_prepare_call_from_config
    template.render_complex(config[CONF_SERVICE_DATA_TEMPLATE], variables)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 71, in render_complex
    return {key: render_complex(item, variables) for key, item in value.items()}
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 71, in <dictcomp>
    return {key: render_complex(item, variables) for key, item in value.items()}
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 73, in render_complex
    return value.async_render(variables)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 224, in async_render
    raise TemplateError(err)
homeassistant.exceptions.TemplateError: UndefinedError: 'dict object' has no attribute 'RfReceived'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 153, in _async_step
    self, f"_async_{cv.determine_script_action(self._action)}_step"
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 623, in _async_call_service_step
    *self._prep_call_service_step(), blocking=True, context=self._context
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 252, in _prep_call_service_step
    return async_prepare_call_from_config(self._hass, self._action, self._variables)
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 135, in async_prepare_call_from_config
    raise HomeAssistantError(f"Error rendering data template: {ex}") from ex
homeassistant.exceptions.HomeAssistantError: Error rendering data template: UndefinedError: 'dict object' has no attribute 'RfReceived'
2020-05-07 15:42:52 ERROR (MainThread) [homeassistant.helpers.condition] Error during template condition: UndefinedError: 'dict object' has no attribute 'RfReceived'
2020-05-07 15:42:52 ERROR (MainThread) [homeassistant.helpers.condition] Error during template condition: UndefinedError: 'dict object' has no attribute 'RfReceived'
2020-05-07 15:42:52 ERROR (MainThread) [homeassistant.helpers.condition] Error during template condition: UndefinedError: 'dict object' has no attribute 'RfReceived'
2020-05-07 15:42:52 ERROR (MainThread) [homeassistant.helpers.condition] Error during template condition: UndefinedError: 'dict object' has no attribute 'RfReceived'
2020-05-07 15:53:23 INFO (MainThread) [homeassistant.components.automation] Executing [SYS] DEMUX RF Sensor
2020-05-07 15:53:23 INFO (MainThread) [homeassistant.components.automation] [SYS] DEMUX RF Sensor: Running script
2020-05-07 15:53:23 INFO (MainThread) [homeassistant.components.automation] [SYS] DEMUX RF Sensor: Executing step call service
2020-05-07 15:53:23 INFO (SyncWorker_17) [homeassistant.components.python_script] Executing rfbridge_demux.py: {'payload': '0x14000C'}

this is my Automation:

- alias: '[SYS] DEMUX RF Sensor'
  trigger:
  - platform: mqtt
    topic: tele/temp/RESULT
  action:
  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{trigger.payload_json.RfReceived.Data}}'

this is my script:

d = { 
# Codici RF per Tasmota e per OMG
      
# Codici sensori magnetici per Tasmota      
      '0x4AD50A':['portone','ON','true'],
      '0x4AD50E':['portone','OFF','true'],
      '0x4AD506':['portone_bat','ON','false'],
#
      '0x4A820A':['fin_sala','ON','true'],
      '0x4A820E':['fin_sala','OFF','true'],
      '0x4A8206':['fin_sala_bat','ON','false'],
#
      '0xD9140A':['fin_bagnop','ON','true'],
      '0xD9140E':['fin_bagnop','OFF','true'],
      '0xD91406':['fin_bagnop_bat','ON','false'],
#
      '0x5C5A0A':['fin_bagnog','ON','true'],
      '0x5C5A0E':['fin_bagnog','OFF','true'],
      '0x5C5A06':['fin_bagnog_bat','ON','false'],
#
      '0x44350A':['fin_camera_vale','ON','true'],
      '0x44350E':['fin_camera_vale','OFF','true'],
      '0x443506':['fin_camera_vale_bat','ON','false'],
#
      '0xD8040A':['fin_camera_cri','ON','true'],
      '0xD8040E':['fin_camera_cri','OFF','true'],
      '0xD80406':['fin_camera_cri_bat','ON','false'],
#
      '0x3F7D0A':['fin_cucinap','ON','true'],
      '0x3F7D0E':['fin_cucinap','OFF','true'],
      '0x3F7D06':['fin_cucinap_bat','ON','false'],
#
      '0xD85C0A':['fin_cucinag','ON','true'],
      '0xD85C0E':['fin_cucinag','OFF','true'],
      '0xD85C06':['fin_cucinag_bat','ON','false'],
#
      '0x4AAE0A':['fin_camera_letto','ON','true'],
      '0x4AAE0E':['fin_camera_letto','OFF','true'],
      '0x4AAE06':['fin_camera_letto_bat','ON','false']
    }

p = data.get('payload')

if p is not None:
  if p in d.keys():
    service_data = {'topic':'home/RF433/{}'.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)

the script resend the MQTT message too and all works fine, but i wont to remove this error.

some one have this error too?

Here’s a redacted excerpt of your log showing a normal execution of the automation, where it receives the data in the proper format, and passes the received value to the python_script.

15:53:23  Executing [SYS] DEMUX RF Sensor
15:53:23  [SYS] DEMUX RF Sensor: Running script
15:53:23  [SYS] DEMUX RF Sensor: Executing step call service
15:53:23 INFO  Executing rfbridge_demux.py: {'payload': '0x14000C'}

Here’s a redacted excerpt showing an abnormal execution of the automation.

15:42:52  Executing [SYS] DEMUX RF Sensor
15:42:52  [SYS] DEMUX RF Sensor: Running script
15:42:52  [SYS] DEMUX RF Sensor: Executing step call service
15:42:52  ERROR  [SYS] DEMUX RF Sensor: Error executing script. Unexpected error for call_service at pos 1: Error rendering data template: UndefinedError: 'dict object' has no attribute 'RfReceived'

The error is occurring in the automation. Sometimes the data it receives is not in the desired format, namely it lacks an RfReceived attribute.

Error rendering data template: UndefinedError: ‘dict object’ has no attribute ‘RfReceived’

It appears that there are times when the topic tele/temp/RESULT is receiving a message that is not in the expected format (i.e. it is missing the RfReceived attribute). It fails to have this format:

{"RfReceived":{"Sync":14110,"Low":480,"High":1380,"Data":"12345E","RfKey":"None"}}

I have no idea why that happens. All I can offer is to modify the automation so that it rejects messages that lack the RfReceived attribute.

- alias: '[SYS] DEMUX RF Sensor'
  trigger:
  - platform: mqtt
    topic: tele/temp/RESULT
  condition:
  - condition: template
    value_template: >
      {{ trigger.payload_json is defined and
         trigger.payload_json.RfReceived is defined and 
         trigger.payload_json.RfReceived.Data is defined }}
  action:
  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{trigger.payload_json.RfReceived.Data}}'

HI… Seek some help. I have configured the scripts but getting the error.
Was not able to find the fault.

rfbridge_demultiplexer: Error executing script. Unexpected error for call_service at pos 1: Error rendering data template: UndefinedError: ‘trigger’ is undefined