Sonoff RF Bridge. Strategies for receiving data

It works rather nice but as already mentioned there is a lag compared to python_script despite running automation in parallel mode. Mostly feelable with e.g. doorbells. Anyway it is OK but for now I continue using script.
Best, JR

1 Like

Given that two out of three users report noticing a ā€œlagā€, I think Iā€™ll leave the first post as-is (i.e. use the python_script). If someone encounters a problem using the python_script, they have an alternative available (i.e. use the new ā€™ all-in-oneā€™ automation).

I have to admit Iā€™m surprised to hear the automation is slower than the python_script. I would have never imagined the performance difference would be so great that it would be detectable through observation and not even requiring any timing tests. Not sure why the automation is so much slower than the python_script. :thinking:

About your new demultiplexer automation (thanks a lot!), I only had to change the initial condition because the original was not working; I changed to:

{{ data[trigger.payload_json.RfReceived.Data] != null }}

With this modification, itā€™s working pretty well, with no performance issues.

Best

1 Like

This will fail to reject payloads that are not in JSON format:

{{ data[trigger.payload_json.RfReceived.Data] != null }}

If the received payload is an empty string or just any string thatā€™s not in JSON format, Home Assistant will report it as an error because the condition attempts to access keys (.RfReceived.Data) that donā€™t exist.

Lag is not so big here. Itā€™s working nice in parallel mode, as I told.
Iā€™ll continue with ā€œall in oneā€ for now. I like it and I need more time to evaluate.
Good job mate!

1 Like

Iā€™m now only using the all in one automation in the parallel mode and works very well for me with no noticeable lag.

Thank you

1 Like

Iā€™m now successfully using the demux on 0.118 without any changes.

Hi to all,

thanks a lot for the automation, now iā€™m using the Taras automation instead the python script.
all works fine, but when i receive a code tha is not present in the variables i receive an error:

2020-11-20 15:43:23 INFO (MainThread) [homeassistant.components.automation.alrm_rf_demux] [ALRM] RF demux: Choose at step 1: default: Running automation actions
2020-11-20 15:43:23 INFO (MainThread) [homeassistant.components.automation.alrm_rf_demux] [ALRM] RF demux: Choose at step 1: default: Executing step call service
2020-11-20 15:41:29 ERROR (MainThread) [homeassistant.components.automation.alrm_rf_demux] [ALRM] RF demux: Choose at step 1: default: 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 351, in async_render
    render_result = compiled.render(kwargs)
  File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/usr/local/lib/python3.8/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.8/site-packages/jinja2/sandbox.py", line 407, in getattr
    value = getattr(obj, attribute)
jinja2.exceptions.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/service.py", line 144, in async_prepare_call_from_config
    service_data.update(template.render_complex(config[conf], variables))
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 91, in render_complex
    return {
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 92, in <dictcomp>
    render_complex(key, variables): render_complex(item, variables)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 96, in render_complex
    return value.async_render(variables)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 353, in async_render
    raise TemplateError(err) from 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 253, in _async_step
    await getattr(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 432, in _async_call_service_step
    domain, service, service_data = async_prepare_call_from_config(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 146, 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'

this my automation:

  - alias: '[ALRM] RF demux nitghtoff'
    mode: parallel
    variables:
      data: { '0xB24E54':['RC1_NIGHT','OFF','true'], # remote RC su Tasmota
              '0x434454':['RC2_NIGHT','OFF','true'], # remote RC su Tasmota
# remote RC su OMG
              '11685460':['RC1_NIGHT','OFF','true'],
              '4408404':['RC2_NIGHT','OFF','true']
      }
    trigger:
    - platform: mqtt
      topic: tele/RF2/RESULT
    - platform: mqtt
      topic: tele/RF1/RESULT
    - platform: mqtt
      topic: home/OpenMQTTGateway_ESP8266_RF/433toMQTT
    condition: '{{ trigger.payload_json is defined }}'
    action:
    - choose:
      - conditions: '{{ trigger.payload_json.RfReceived.Data in data.keys() }}'
        sequence:
        - service: mqtt.publish
          data:
            topic: 'home/RF433/{{ data[trigger.payload_json.RfReceived.Data][0] }}'
            payload: '{{ data[trigger.payload_json.RfReceived.Data][1] }}'
            qos: 0
            retain: '{{ data[trigger.payload_json.RfReceived.Data][2] }}'
      default:
      - service: mqtt.publish
        data:
          topic: 'home/unknown'
          payload: '{{ trigger.payload_json.RfReceived.Data }}'
          qos: 0
          retain: false

BR

Actually, itā€™s a bit more severe than a non-existent code. The received payload fails to contain ā€˜RfReceivedā€™. Thatā€™s what this error message is reporting:

UndefinedError: ā€˜dict objectā€™ has no attribute ā€˜RfReceivedā€™

I suggest you enhance the condition so it ensures the payload contains the ā€˜RfReceivedā€™ key.

  condition: >
    {{ trigger.payload_json is defined and
       trigger.payload_json.RfReceived is defined }}

EDIT

Correction. Replaced RFReceived with RfReceived.

with this noting was tiggered:

condition: >
    {{ trigger.payload_json is defined and
       trigger.payload_json.RFReceived is defined }}

but working fine without any error regarding dict_object whit this:

condition: '{{ trigger.payload_json.RfReceived is defined }}'

Because thereā€™s a typo in the template. It refers to RFReceived instead of RfReceived. Iā€™ve corrected my previous post. Try it again and youā€™ll see it works properly (Iā€™ve tested it).

The problem with using only the following condition is that it will fail if the received payload is not in JSON format:

condition: '{{ trigger.payload_json.RfReceived is defined }}'

It will generate this error message:

Error during template condition: UndefinedError: ā€˜dict objectā€™ has no attribute ā€˜payload_jsonā€™

Thanks a lot now it works perfecly

First a big ā€œthank youā€ for sharing this informations and code! :smiley:
I did it as described in strategy 2 and it work fine!

But I have one sensor (fire sensor) which is alway ā€œdemuxedā€ in topic unknown, although the payload of the fire sensor is part of de python script. :woozy_face:

python-script (payload on line 15:

d = { '0CD102':['sonoff_button_home_a','ON','false'],
      '0CD108':['sonoff_button_home_b','ON','false'],
      '0CD101':['sonoff_button_home_c','ON','false'],
      '0CD104':['sonoff_button_home_d','ON','false'],
      'EDB0C1':['sonoff_button_key_M_arm_away','ON','false'],
      'EDB0C2':['sonoff_button_key_M_disarm','ON','false'],
      'EDB0C4':['sonoff_button_key_M_arm_home','ON','false'],
      'EDB0C8':['sonoff_button_key_M_sos','ON','false'],
      'FBFF1E':['sonoff_pir_keller_tuere','ON','true'],
      'FC302E':['sonoff_pir_keller_fenster','ON','true'],
      'D2792E':['sonoff_pir_eingang_aussen','ON','true'],     
      '14CA83':['sonoff_housedoor_lockstatus','ON','true'],
      '14CA89':['sonoff_housedoor_lockstatus','OFF','true'],
      'CA7169':['sonoff_water_waschmaschine','ON','true'],
      '623476':['sonoff_fire_waschkueche','ON','true'],
      '620602':['somfy_cover_alle_storen_up','ON','false'],
      '620604':['somfy_cover_alle_storen_stop','ON','false'],
      '620608':['somfy_cover_alle_storen_down','ON','false'],
      '620612':['somfy_cover_sitzplatz_up','ON','false'],
      '620614':['somfy_cover_sitzplatz_stop','ON','false'],
      '620618':['somfy_cover_sitzplatz_down','ON','false'],
      '620622':['somfy_cover_essen_up','ON','false'],
      '620624':['somfy_cover_essen_stop','ON','false'],
      '620628':['somfy_cover_essen_down','ON','false'],
      '620632':['somfy_cover_balkon_up','ON','false'],
      '620634':['somfy_cover_balkon_stop','ON','false'],
      '620638':['somfy_cover_balkon_down','ON','false'],
      '620642':['somfy_cover_wohnen_up','ON','false'],
      '620644':['somfy_cover_wohnen_stop','ON','false'],
      '620648':['somfy_cover_wohnen_down','ON','false'],
      '620652':['somfy_cover_strasse_up','ON','false'],
      '620654':['somfy_cover_strasse_stop','ON','false'],
      '620658':['somfy_cover_strasse_down','ON','false'],
      '620662':['somfy_cover_sonnenstore_up','ON','false'],
      '620664':['somfy_cover_sonnenstore_stop','ON','false'],
      '620668':['somfy_cover_sonnenstore_down','ON','false'],
      '620672':['somfy_cover_alle_lamellen_up','ON','false'],
      '620674':['somfy_cover_alle_lamellen_stop','ON','false'],
      '620678':['somfy_cover_alle_lamellen_down','ON','false'],
      '620682':['velux_cover_carmen_up','ON','false'],
      '620684':['velux_cover_carmen_stop','ON','false'],
      '620688':['velux_cover_carmen_down','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)

binary_sensor.yaml

- platform: mqtt
  name: 'sonoff_fire_waschkueche'
  state_topic: 'home/sonoff_fire_waschkueche'
  device_class: smoke

And this is what I get in tasmota console as payload:

And this ist whatā€™sin MQTT-Broker:
image

Everything you have presented suggests it should work correctly. However it doesnā€™t which implies it must be due to information that hasnā€™t been discovered or presented here. I have no idea what that missing information might be so I cannot explain why 623476 fails to be found and is reported as unknown.

Hopefully someone else can help you.

Hi taras and thanks a lot this guide.

I use second strategie and i have about 30 rf device connected. Most of them works well, but there are two firedetector that not work. RF Bridge see the code right when sensor send it, but demultiplexer not. I think the problem is in E letter in data third position.

bridge show both right
first:

tele/RF_Bridge/RESULT = {"Time":"2020-11-21T14:17:11","RfReceived":{"Sync":17480,"Low":580,"High":1700,"Data":"63E056","RfKey":"None"}}

second:

tele/RF_Bridge/RESULT = {"Time":"2020-11-21T14:17:14","RfReceived":{"Sync":17320,"Low":580,"High":1680,"Data":"67E946","RfKey":"None"}}

HA give warning in first data:

`2020-11-21 13:17:12 WARNING (SyncWorker_7) [homeassistant.components.python_script.rfbridge_demux.py] <rfbridge_demux> Received unknown RF command: 6.3e+57`

and second

`2020-11-21 13:17:15 WARNING (SyncWorker_3) [homeassistant.components.python_script.rfbridge_demux.py] <rfbridge_demux> Received unknown RF command: inf`

Any idea?

Yes, the hint is here:

Received unknown RF command: 6.3e+57

Itā€™s interpreting "67E946" not as a string but as a number in scientific notation, also known as exponential notation.

In other words, the rfbridge_demultiplexer automation is passing trigger.payload_json.RfReceived.Data, namely 67E946, to the python_script not as a string but as a very large number.

This misinterpretation of strings that look like scientific notation was supposed to be corrected by this PR:

However, it seems like it may have overlooked this particular case.

This is beyond my control so you will have to report this problem as a new Issue in the GitHub Core repository (and reference PR 43170 to provide context).

Thank you Taras for quick reply. =)

@123 when I copy this code without any change in an automation, I get a lot of errors :woozy_face:

@123 thanks for fast answer, so I know code should be right. Iā€™m not sure if this was always a problem but i guess, first it worked fine and the payload ist unkown with one of the last updatesā€¦
Unfortunately I donā€™t know whitch oneā€¦

Based on the error message, you appear to have pasted the automation in the wrong place.

1 Like