Sonoff RF Bridge. Strategies for receiving data

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

:blush: :innocent: ups, I have since 2 days my automations splitted in mulitples files, so I forgott to delete the hyphen “- alias”… in the separated file…

Automation works now fine :smiley:
and the payload 623476 is with automation not unknown !!
but with pythron script still same issue…

I’ve tested some other devices with a payload only with numbers.
Also these are “unkown”, so it seems, that payload’s only with numbers can’t be anymore proceed corretly by the python script.

Syntax change:

old
‘2C8D0A’:[‘sensor1’,‘ON’,‘true’]

new

2C8D0A:[‘sensor1’,‘ON’,‘true’]

As you the know, the only difference between the two is the first is a string and the second is a hexadecimal number. It shouldn’t make a difference which one is used (to serve as the key for a dict) unless version 0.118 automatically converts the received string to a number.

That’s what might be happening given that another user reported that "67E946" (a string) was interpreted to be a number in scientific notation (67 exponent 946).

Yes, indeed, if I change syntax in the python-script for number-only payloads, they are no longer unknown.

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'],

but syntax change only for numeric paiyloads, payloads with letters must kept in ’ ', otherwise these payload are not recognized.

This seems to be some sort of new behavior in 0.118 where it automatically converts a string to an integer if the string is numeric. At least that’s my best guess as to what’s going on.

Sorry I can’t be of more help. This new ‘auto-conversion’ behavior in 0.118 is all new to me as well.

1 Like

In python script, use number-to-string conversion

payload = str(data.get(‘payload’))

1 Like

You’re missing the point. Yes, the python_script can cast everything it receives to string. However, ask yourself why that step was not needed in previous versions?

The answer is because 0.118 has implemented automatic type conversions. If a string looks like an integer, it gets converted to an integer (whether you want it or not).

Where is this happening? It’s happening in templates, right here in the rfbridge demultiplexer automation, when it passes the received payload to the python_script:

  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{trigger.payload_json.RfReceived.Data}}'

If trigger.payload_json.RfReceived.Data contains a numeric string, it gets automatically converted to an integer. This is new behavior in 0.118. In my opinion, if it’s a string it should be left as a string and its type should not be automatically converted to integer just because of its contents (‘type inference’).

Unfortunately, we have no control over the automatic type conversion in templates. For example, let’s say I wanted to ensure the value is always handled as a string so I employ the string filter:

      payload: '{{trigger.payload_json.RfReceived.Data | string}}'

However, in 0.118, it ignores the string filter and continues to convert a numeric string to integer.

I know you’re upset about this change but we truly benefit from the enhancement. Hopefully soon you’ll be able to template keys…

service: notify.notify
data: >
  {% set on_dict = {'message': 'foo'} %}
  {% set off_dict = {'message': 'bar', 'title': 'Bar'} %}
  {% if is_state('xxx.xxx','on') %}
    {{ on_dict }}
  {% else %}
    {{ off_dict }}
  {% endif %}

Imagine the possibilities. Please take your blinders off and look to the future and fix the issues with your script and this change.

In the same spirit as your reply, please open your eyes to the possibility of allowing users to decide when a type should be converted and when it should not. Currently, a user has no control over type conversion.

As for the suggestion to “fix the issues with your script”, it can be done in python_script because we still have the ability to control type. However, the new ‘all-in-one’ automation I recently posted cannot be “fixed” because 0.118 gives me no control over type in templates.

The only way to accomodate the new reality is to change the keys in the dict to match the auto-converted type.

Imagine the possibilities if you could control the type in an automation’s template. You could tell it to always treat trigger.payload_json.RfReceived.Data as a string and then you wouldn’t have to modify keys in the dictionary.

:man_shrugging: You’re arguing to the wrong person. I’m simply telling you that the best option is to adapt and overcome. I’m not going to part take in an discussion to add some field for typing, or give the user the ability to strongly type it.

I personally welcome the change and no amount of discussion will change my personal opinion. I also think that all template changes and enhancements should occur in the single template without additional fields. You won’t change my opinion on that matter either.