HA to RF 433 gateway and how to set up binary_sensors to work with RF payloads

Hi everyone,

Setting up HA with RF devices can be a bit tricky. I wrote a tutorial type post explaining how I did it. It’s a neat approach and would like to know what you think.

Setting up RF binary sensors in HA

I later dockerised the OpenMQTTGateway, to run it directly on Raspberry Pi with attached RF sensors. Check it out here

I try to produce helpful blog content and hoping to accumulate an audience. Happy to hear your feedback.

4 Likes

I find this to be easier and offer more flexibility…

sensor:
  - platform: mqtt
    state_topic: 'omg/+/433toMQTT'
    name: last_433
    expire_after: 1

The expire_after: 1 makes sure that the last received code doesn’t appear to be sending constantly.

Then, to make a “triggering” binary sensor (like for a button press, or a PIR sensor), I do this:

binary_sensor:
  - platform: template
    sensors:
      office_motion_433:
        value_template: '{{ is_state("sensor.last_433", "2258554") }}'
        delay_off: '00:05:30'
        device_class: motion

The “delay_off” of each of these sensors is set to something slightly longer than the retrigger time of that particular sensor. This way, the sensor stays “on” for the entire motion period, and turns off once it’s no longer detected motion.

This allows for each sensor to be configured according to how it works, and also allows for a single, continuous motion event on each sensor, instead of seeing “on” then “off” 5 seconds later over and over again through the motion event.

Cool way to do it. I used to have a very similar set up, but it got really messy once I added more RF devices.

That’s one of the nice things about Home Assistant and DIY components… there are often many, many ways to do the same thing.

I don’t quite understand how your configuration would be LESS messy with more RF devices than mine.

In your method, you have a binary_sensor/mqtt entry for every RF device. As well as an automation to publish a “0” after every seen event on an MQTT topic (an automation that, as you know, goes out of HASS, into MQTT, and then back into HASS). So, you have N devices and 1 automation (plus whatever else you need to actually do things when the RF devices trigger). In terms of CPU, every one of these binary_sensors will trigger every time the topic updates (which is twice per RF trigger, one for the code, and again for the 0).

In my method, I have a binary_sensor/template entry for every RF device. And I have a sensor/mqtt entry for the RF topic. So I have N+1 devices and no automations. In terms of CPU, every one of my binary_sensors will trigger every time the sensor updates (which is once per RF trigger, plus once every time the sensor expires).

So in terms of configuration, they are equal. In terms of CPU time, they are roughly equal (yours is probably a tiny bit worse because of the overhead of sending a 0 to mqtt only to have it read back in by Hass). So the amount of mess with either of our methods is the same. My method, however, has the added feature of leaving the sensor ON for the proper length of time based on a setting for each RF device. Your method, leaves the sensor on for 1 second, no matter what. And if you didn’t want that feature, for whatever reason, you could just not set “delay_off” at all, and get the exact same functionality you have (1 second on, then off).

I’m a fan of there being many ways to do the same thing all with different benefits. But in this case, I don’t understand how mine is messy and yours is not. If there’s something about your setup that is cleaner that I’m not understanding, I’d like to understand so I can do it that way instead.

Hi @swiftlyfalling

Nice approach. I used to do the same with timers, or automation like the one did by @danny. Yours seen better than what I do now. But what happens when you have a stream of codes on MQTT? If, for instance, you have two PIR sensors on the same area and they both get triggered? Another question: when you got a PIR code before the delay_off, this “counter” is reseted, right? ty

So, the binary sensor is always watching the sensor.last_433 (in my case). Which means, without the delay_off, it would turn on when it saw the right code, and then turn off immediately after any other code is seen. With the delay off set to, say, 1 minute, it turns off 1 minute after any other code is seen. However, if a code is sent, and then no other code is ever sent again, it would stay on forever. That’s why the sensor.last_433 also needs the expire_after: 1 setting. This means that sensor.last_433 will be equal to the last seen code, but only for 1 second. So, with a delay_off of one minute, it’ll actually take 1 minute and 1 second for the binary sensor to turn off after it is triggered.

Because the binary_sensor is technically “off” after 1 second (when the sensor.last_433 code expires) if you trigger the same code again, it represents a state change, so the “delay_off” starts over on the binary_sensor thus giving you exactly the behavior you’d expect in this circumstance. As long as the code is triggered again before the delay_off time is reached, then the sensor appears to stay on forever. As soon as the code is not seen for delay_off + 1second, then the binary_sensor turns off.

Hi,

I’m testing it now and it’s working as expected, but for now I only have one PIR sensor. I’m worried about what would happen when I add more sensors.

I have 12 PIR sensors as well as 8 wall mounted 433Mhz remotes (same idea as a PIR sensor, with a code to trigger it, just mounted on a wall and waiting for a button press instead of detecting motion) and 4 handheld 433Mhz remotes. They all use the same sensor.last_433 to get their data and they all work flawlessly.

For the buttons, since they don’t have a “delay_off” that makes any sense… since it’s a button that is pressed, I use an automation that triggers a button press event… like this:

- alias: Living Button Box 1 event
  trigger:
    - platform: state
      entity_id: sensor.last_433
      to: '10516850'
  action:
    - event: button.living_box_1

I did the same thing using AppDaemon. Allows reuse of code, just passing in different codes for each RF device.
Listens to a code on MQTT and emits a named event for each known code.

Yes! AppDaemon is a great choice for things like this. I used to use it for this task and it was working quite well. Then, either my system got too big (too many state changes) or integration got slower between AppDaemon and HASS… but whatever happened, I started noticing too much of a delay between triggering the sensor and seeing the state change in HASS. I use motion senors to turn on lights in dark rooms when someone enters and it was taking too many steps into the room before the lights came on. I removed one sensor from AppDaemon and implemented it directly in a Home Assistant automation (like I described above) and it was much faster. So I got rid of my use of AppDaemon for this.

I’ve since upgraded my Home Assistant server from a Raspberry Pi to a full blown Ubuntu machine which is much much faster. So I could probably go back to the AppDaemon route and have it be fast enough again, but this works just fine too.

(off topic: if you have an interesting or useful AppDaemon modules you’d like to share, I’d love to see them)

I am getting a noticeable delay like you describe but haven’t had the chance to debug and find out where the delay actually happens.
I’ve implemented MotionLights in AppDaemon. Check it out here

1 Like

It seemed the delay issue was network related as the delay is down to <1s end to end ever since I added a Asus wifi router to the network. (As opposed to running everything through a modem). This is fast enough to be practical. The previous delay of 3-5 seconds was driving me nuts…

I wanted to say thanks for this reference. In my opinion it is cleaner than other methods in dealing with a sensor which isn’t designed to reset its own state.

To help others with a Sonoff RF Bridge, here is a modified version:

    sensor:
      # RF Bridge as sensor - "Data" is the truncated (unique) hex address of the transmitter
      - platform: mqtt
        state_topic: 'tele/SonoffRFBridge/RESULT'
        name: Sonoff Bridge
        value_template: "{{ value_json.RfReceived.Data }}"
        expire_after: 1

and a proximity motion sensor:

    binary_sensor:
    - platform: template
      sensors:
        sonoff_pir_1:
          value_template: '{{ is_state("sensor.sonoff_bridge", "A0C1D2") }}' 
          delay_off: '00:00:05'
          device_class: motion
          friendly_name: "PIR One"
2 Likes

When I implemented it the expire_after and/or delay_off parameters were not available. (Which is why i had to work around it). Does this setup handle RF codes from multiple devices? What happens when RF code 100 is sent followed by 200 some 5 seconds later?
I would be interested if I can use this in my setup.

Does this setup handle RF codes from multiple devices? What happens when RF code 100 is sent followed by 200 some 5 seconds later?

Yes it does. The sensor element is simply capturing the last code sent, and in theory, you could buffer some number (N) of codes if you need to access the last (N) codes, but you would handle (or ignore) code ‘100’ and then handle (or ignore) code ‘200’ in sequence. As long as you have a binary_sensor setup to handle each of your codes, you will be able to access them in the value_template with the is_state() function.

Try it out and let us know!

1 Like

Hi,
The MQTT Binary Sensor documentation says the delay_off parameter should be off_delay. (see link).
Can you confirm this is a mistake in the documentation? Given it works for you?
I can’t get either to work with the following configuration:

- platform: mqtt
  name: "test_living_room_motion_test"
  device_class: 'motion'
  state_topic: "/rf/2678906"
  off_delay: 3

Note that the delay should be specified in the Template Binary Sensor, and not the MQTT Sensor. As such, the delay_off parameter is a part of https://www.home-assistant.io/components/binary_sensor.template/

You should be setting up a (non-binary) sensor of type MQTT (which will detect / change to any of the received RF codes), and then for each RF device, you will create a Template Binary Sensor. So far I have successfully created two template binary sensors derived from the data being observed in the MQTT sensor which is my Sonoff RF bridge.

I can skip the generic binary sensor because my RF codes are sent on unique topics. e.g. /rf/2678906
Updating Home Assistant did the trick. It seems the off_delay parameter was introduced somewhere between 0.79 and 0.81. Awesome!

This is much better than the common solutions in another thread which involves spoofing mqtt messages from hass to hass! I spent a couple of hours trying to get rid of this error message and reading through another thread on here:

2019-01-05 13:35:31 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: 'value_json' is undefined (value: {“RfReceived”:{“Data”:"C15554off"}}, template: {{ value_json.RfReceived.Data }})

So I found this solution offered by @danny The only difference I have is I am using tasmota now and not openmqttgateway. Tasmota sends the codes as json. So This is what I did:

binary_sensor:
  - platform: mqtt
    name: "Kitchen Motion"
    payload_on: "757534"
    device_class: motion
    state_topic: "rf_bridge/tele/RESULT"
    value_template: "{{ value_json.RfReceived.Data }}"
    off_delay: 180

This works great and reduces the number of lines in your config substantially if you have lots of sensors like I do.
I still get the error message above, but as I dont have “C15554off” anywhere in my config any more I know it is stale data that will probably go away when my database is purged.

1 Like

I have since created this custom component which sends events when configured RF codes are received on a specific topic.