Sonoff RF Bridge. Strategies for receiving data

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

This is the suggested automation:

- 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}}'

Does your version look like that? If not, please post it so I can examine it.
Also, have you configured the python_script integration according to its instructions?

I’m missing something simple, I’m sure, and my talent is now exhausted.

I’ve been using the demux for ages with great success and have rebuilt my HA instance on a new machine.

And now none of my RF bridges messages are being seen by HA.

I can see the messages in MQTT Explorer and Mosquitto is working fine with other MQTT devices.

Here’s what I have and some examples of my binary sensor configs. None of this has been edited since migrating to the new machine.

- alias: 'rfbridge_demultiplexer'
  trigger:
  - platform: mqtt
    topic: tele/Garage_RF_Bridge/RESULT
  - platform: mqtt
    topic: tele/RF_bridge_west/RESULT
  - platform: mqtt
    topic: tele/RF_bridge_east/RESULT
  - platform: mqtt
    topic: tele/RF_bridge_stable/RESULT
  - platform: mqtt
    topic: tele/RF_bridge_1st_floor/RESULT
  action:
  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{trigger.payload_json.RfReceived.Data}}'
d = { 'D3226E':['garage_motion','ON','false'],
      '51F65A':['telegraph_pole_garage','ON','false'],
      '119B0A':['garage_door','ON','true'],
      '119B0E':['garage_door','OFF','true'],
      '715FFF':['gym_motion','ON','false'],
      '9F150A':['garage_motion_2','ON','false'],
      '49732E':['courtyard_gates','ON','true'],
      '497327':['courtyard_gates','OFF','true'],
      '2479EE':['catflap','ON','true'],
      '2479E7':['catflap','OFF','true'],
      '85D80A':['oskaflap','ON','true'],
      '85D80E':['oskaflap','OFF','true'],
      'F9010A':['back_door','ON','true'],
      'F9010E':['back_door','OFF','true'],
      '91F60A':['gym_door','ON','true'],
      '91F60E':['gym_door','OFF','true'],
      # '545F10':['back_door_motion','ON','false'],
      '71BDEE':['front_door','ON','true'],
      '71BDE7':['front_door','OFF','true'],
      'C5790A':['fridge','ON','true'],
      'C5790E':['fridge','OFF','true'],
      'A68B23':['letterbox','ON','false'],
      '142186':['stable_motion','ON','false'],
      '54F65A':['north_east_pir','ON','false'],
      '45F64A':['north_central_pir','ON','false'],
      '4DF64A':['north_west_pir','ON','false'],
      '49F64A':['garage_north_pir','ON','false'],
      '59F65A':['pergola_pir','ON','false'],
      '6DF66A':['courtyard_pir','ON','false'],
      '61F66A':['south_central_pir','ON','false'],
      'AA0D0A':['south_central_pir_2','ON','false'],
      '850E0A':['south_east_pir','ON','false'],
      '780E0A':['firepit_pir','ON','false'],
      '32F63A':['carpark_pir','ON','false'],
      '64F66A':['driveway_1_pir','ON','false'],
      '42F64A':['driveway_2_pir','ON','false'],
      '545F10':['firepit_2_pir','ON','false'],
      '3EF63A':['garage_west_pir','ON','false'],
      '85E9EE':['gun_cabinet_door','ON','true'],
      '85E9E7':['gun_cabinet_door','OFF','true'],
      '54F65F':['north_east_pir_battery','ON','false'],
      '45F64F':['north_central_pir_battery','ON','false'],
      '4DF64F':['north_west_pir_battery','ON','false'],
      '49F64F':['garage_north_pir_battery','ON','false'],
      '59F65F':['pergola_pir_battery','ON','false'],
      '6DF66F':['courtyard_pir_battery','ON','false'],
      '61F66F':['south_central_pir_battery','ON','false'],
      'AA0D0F':['south_central_pir_2_battery','ON','false'],
      '850E0F':['south_east_pir_battery','ON','false'],
      '780E0F':['firepit_pir_battery','ON','false'],
      '32F63F':['carpark_pir_battery','ON','false'],
      '64F66F':['driveway_1_pir_battery','ON','false'],
      '42F64F':['driveway_2_pir_battery','ON','false'],
      '545F1F':['firepit_2_pir_battery','ON','false'],
      '3EF63F':['garage_west_pir_battery','ON','false'],
      '861B2F':['courtyard_gates_battery','ON','false'],
      '71BDEF':['front_door_battery','ON','false'],
      '85E9EF':['gun_cabinet_door_battery','ON','false'],
      '2479EF':['catflap_battery','ON','false'],
      '85D80F':['oksaflap_battery','ON','false'],
      'A74723':['awning_vibration','ON','false'],
      'A7472F':['awning_vibration_battery','ON','false'],
      '51F65F':['telegraph_pole_garage_battery','ON','false'],
      '9F150F':['garage_motion_2_battery','ON','false'],
      'C5790F':['fridge_battery','ON','false'],
      'D3226F':['garage_motion_battery','ON','false'],
      'F9010F':['back_door_battery','ON','false'],
      'A68B2F':['letterbox_battery','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)
    - platform: mqtt
      name: 'Garage Door'
      state_topic: 'home/garage_door'
      device_class: Door

    - platform: mqtt
      name: 'Gym Door'
      state_topic: 'home/gym_door'
      device_class: Door

    - platform: mqtt
      name: 'Gym Motion'
      state_topic: 'home/gym_motion'
      off_delay: 3
      device_class: Motion

MQTT settings have been appropriately changed in the Tasmota configs.

I’d appreciate any advice on where to look to fix this.

I assume you have used MQTT Explorer to confirm that your RF bridges are publishing to their respective topics:

tele/Garage_RF_Bridge/RESULT
tele/RF_bridge_west/RESULT
tele/RF_bridge_east/RESULT
tele/RF_bridge_stable/RESULT
tele/RF_bridge_1st_floor/RESULT

I suggest you:

  1. Use Developer Tools > States to confirm the state of automation.rfbridge_demultiplexer is on. Turn it on if is currently off.
  2. Use Developer Tools > Services to confirm python_script.rfbridge_demux is an available service. If it’s not present, double-check that you have installed the python_script integration correctly.

I just knew it had to be something obvious that wasn’t obvious to me. Installing it now.

Thank you so much.

Yeah, that would’ve been an easy thing to overlook to do when you switched to a complete new machine.


EDIT

Thanks for mentioning that you had created a new machine. Had you left out that detail, it would’ve taken more time and effort to debug the problem.

1 Like

All working now. Thanks again.

1 Like

Thanks!!! Works great and really easy to follow instructions. :+1:

1 Like

added some more python to it

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:
   bla_bla = "'{}':['-+-+-+-+','ON','true/false'],".format(p)
   b_sensor = "binary_sensors \n - platform: mqtt \n name: 'new  binary sensor Name'\n state_topic: 'home/-+-+-+-+' \n device_class: door \n off_delay: 1".format(p)
   hass.services.call('persistent_notification', 'create',{'message':'{} \n\n copy above code \n paste it into the rfbridge_demux.py \n \n {}'.format(bla_bla,b_sensor), 'title':'NEW RF CODE'})
   service_data = {'topic':'home/unknown', 'payload':'{}'.format(p), 'qos':0, 'retain':'false'}
 hass.services.call('mqtt', 'publish', service_data, False)

if does not know the RF code it create a notification for you
in right sh format so you can just copy/paste it.

image

hope it help someone

just had a BRAIN FART if you have a tasmota IR

and just change the topic and it payload

to the IR protocol

- alias: 'IR_Bridge Data'
  trigger:
  - platform: mqtt
    topic: tele/IR/RESULT
  action:
  - service: python_script.rfbridge_demux
    data_template:
      payload: '{{trigger.payload_json.IrReceived}}'

You can you use the same logic in python script

this is a IR code

image

2 Likes

I have found this tread and the python code from @123 karas amazing helpful. But while pointing it out to a YAML guru, he showed me this. I am using the python strategy #2 and don’t plan on changing, BUT if you what YAML code that will work for this, I think this will and won’t trigger the log spam. This appears to be the way HA is intended to work for things like this.

- platform: mqtt
  name: this_door
  state_topic: tele/RF_Bridge/RESULT
  value_template: >
    {%- if value_json['RfReceived'].Data is defined and value_json['RfReceived'].Data['E4180!'] is defined -%}
      {%- if value_json['RfReceived'].Data == 'E4180E' -%}
      ON
      {%- elif value_json['RfReceived'].Data == 'E4180A' -%}
      OFF
    {% endif %}
    {% else %}
      {{ states('binary_sensor.this_door') }}
    {% endif %}
  availability_topic: "tele//RF_Bridge/LWT"
  payload_available: "Online"
  payload_not_available: "Offline"
  device_class: door
  qos: 1

It specifically looks for your code base, the common digits in the data that are the same and this can be used as the device identifier. If it doesn’t see it, it just sends back the current state. This should not trigger the warnings.
I did not plug this code in and test it, so if it needs touch-up let’s fix it, vut I took what he had and plugged in rfbridge stuff (instead of zigbee bridge stuff) and you see the principal. It gives the sensotr an out if the value revieved is not one of these.

Effectively, that’s Strategy #1 except the template takes the additional precaution of confirming the payload contains the variable value_json.RfReceived.Data prior to using it.

The important part is that it verifies that the data recieved is from the sensor that you are looking for, IE the common part of the data that makes this code unique to this sensor. If it’s not, it just returns the current state, so HA will not care or see you as having multiple answers for the same (as opposed to ON/OFF)
The important part is that it verifies that the data received is from the sensor that you are looking for, IE the common part of the data that makes this code unique to this sensor. If it’s not, it just returns the current state, so HA will not care or see you as having multiple answers for the same (as opposed to ON/OFF)
@blakadder showed me this on stuff from his zigbee bridge, so I did the same here as an example

You may wish to review the first post in this thread because you literally described how “Strategy 1: value_template” operates. It works exactly as you just explained.

Hmm. I guess so. Apparently 2 years ago when i read that I didn’t understand it, and loved strategy 2 so much I never gave another thought about it (until called on it). Oh, well, this is a little different, bit more efficient when not the device called as it aborts in 1 -if- instead of 2. It might help someone…

I’m glad to hear you now understand it uses the same approach presented in Strategy 1.

Have you tested it? I have and it’s not more efficient, in fact, it doesn’t even work.

Aside from this minor syntax error in the availability_topic

availability_topic: "tele//RF_Bridge/LWT"
                         ^

the real problem is this error in the second test:

and value_json['RfReceived'].Data['E4180!'] is defined
                                 ^^^^^^^^^^

in dot notation, the template expects a JSON path like this:

value_json.RfReceived.Data.E4180!

The payload’s JSON structure looks something like this:

{ "RfReceived":{ "Data":"E4180E" } }

However, the template’s JSON path expects the payload to look something like this:

{ "RfReceived":{ "Data":{"E4180!": "??" } } }

It will never have that structure so the second test in the template always evaluates to false. That means the result returned is always this:

{{ states('binary_sensor.this_door') }}

That template is also incorrect because of the reason explained in the first post. The state of a binary_sensor is lower case on or off and that’s what the states() function will report. However, it should be supplying upper case ON or OFF because that’s the default payload expected by an MQTT Binary Sensor.

payload_on
(string)(Optional)

The string that represents the on state. It will be compared to the message in the state_topic (see value_template for details)

Default value:

ON


EDIT
You can prove it to yourself using the Template Editor.

This reports NO because the payload’s JSON structure doesn’t match the template’s JSON path.

This reports YES because the payload’s JSON structure does match the template’s JSON path. However, a Sonoff RF Bridge doesn’t transmit its payload with that structure.

Being an RF signal, when 2 broadcast in the same time the brodcast is garbles and the codes are not correct. I have a PIR and a door reed sensor very close, so often I open the door and the door movements triggers the PIR, so I will get garble…