Sonoff RF Bridge with ESPHOME?

Don’t cut anything on your bridge. There is absolutely no need to. It’s a horrible hack job. Search for the guide i posted on it.

I tried to create a binary sensor inside esphome - this option seemed to me the most convenient. I tried to do it in two ways. In each of these two ways, I ran into the same error:
In the esphome web interface, only a part of the sensors becomes active, active sensors become visible in the homeassistant, the rest are not. When I start using the devices, everything is correct in the logs, each window activates the desired sensor, but in the web interface “window 1” activates “window 1”, but “window 2” also activates “window 1”, although in the logs I see a trigger sensor “window 2” and no activity “window 1”. Help organize the binary sensors correctly.

esphome:
  name: sonoff_rfbridge
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: "xxx"
  password: "xxx"
  
api:
  password: "xxx"
  services:
    - service: send_rf_code
      variables:
        sync: int
        low: int
        high: int
        code: int
      then:
        - rf_bridge.send_code:
            sync: !lambda 'return sync;'
            low: !lambda 'return low;'
            high: !lambda 'return high;'
            code: !lambda 'return code;'
    - service: learn
      then:
        - rf_bridge.learn

uart:
  tx_pin: 1
  rx_pin: 3
  baud_rate: 19200

logger:
  baud_rate: 0

rf_bridge:
  on_code_received:
    then:
      - text_sensor.template.publish:
          id: rf_code
          state: !lambda 'char buffer [10];return itoa(data.code,buffer,16);'
      - homeassistant.event:
          event: esphome.rf_code_received
          data:
            sync: !lambda 'char buffer [10];return itoa(data.sync,buffer,16);'
            low: !lambda 'char buffer [10];return itoa(data.low,buffer,16);'
            high: !lambda 'char buffer [10];return itoa(data.high,buffer,16);'
            code: !lambda 'char buffer [10];return itoa(data.code,buffer,16);'

ota:
  password: "xxx"

web_server:
  port: 80

sensor:
        
#  WiFi Signal Sensor
#  Датчик отображающий уровень сигнала Wifi
  - platform: wifi_signal
    name: "Sonoff Rfbridge WiFi Signal"
    update_interval: 60s
    
#  Uptime Sensor

#  Датчик отображающий время работы
  - platform: uptime
    name: "Sonoff Rfbridge Uptime"
    id: sonoff_rfbridge_uptime
    update_interval: 60s
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human_rfbridge
            state: !lambda |-
              int seconds = round(id(sonoff_rfbridge_uptime).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? String(days) + "d " : "") +
                (hours ? String(hours) + "h " : "") +
                (minutes ? String(minutes) + "m " : "") +
                (String(seconds) + "s")
              ).c_str();

binary_sensor:


  - platform: template
    name: "Дверь входная"
    id: dver_vhodnaya

  - platform: template
    name: "Окно гостиная 1"
    id: okno_gostinaya_1

  - platform: template
    name: "Окно гостиная 2"
    id: okno_gostinaya_2

  - platform: template
    name: "Окно родители"
    id: okno_roditeli

  - platform: template
    name: "Окно кухня"
    id: okno_kuhnya

  - platform: template
    name: "Окно санузел 1 этаж"
    id: okno_sanuzel_1_etaz

  - platform: template
    name: "Окно прихожая"
    id: okno_prihozaya

  - platform: template
    name: "Окно крыльцо"
    id: okno_krilco

  - platform: template
    name: "Окно санузел 2 этаж"
    id: okno_sanuzel_2_etaz

  - platform: template
    name: "Окно спальня 1"
    id: okno_spalnya_1

  - platform: template
    name: "Окно спальня 2"
    id: okno_spalnya_2

  - platform: template
    name: "Окно детская"
    id: okno_detskaya


light:
  - platform: binary
    name: "Sonoff Rfbridge WiFi LED"
    id: wifi_led
    output: output_wifi_led
    internal: True

output:
  - platform: gpio
    pin:
      number: GPIO13
      inverted: True
    id: output_wifi_led

switch:
  - platform: restart
    name: "Sonoff Rfbridge Restart"


text_sensor:
  - platform: template
    name: "Latest Code"
    id: rf_code
    on_value:
      then:
    # Дверь входная
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'd72f2e'
            then:
              - lambda: |-
                  id(dver_vhodnaya).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'd72f27'
            then:
              - lambda: |-
                  id(dver_vhodnaya).publish_state(false);

    # Окно гостиная 1
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '713b2e'
            then:
              - lambda: |-
                  id(okno_gostinaya_1).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '713b27'
            then:
              - lambda: |-
                  id(okno_gostinaya_1).publish_state(false);

    # Окно гостиная 2
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '8cdb2e'
            then:
              - lambda: |-
                  id(okno_gostinaya_2).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '8cdb27'
            then:
              - lambda: |-
                  id(okno_gostinaya_2).publish_state(false);

    # Окно родители
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '84eb2e'
            then:
              - lambda: |-
                  id(okno_roditeli).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '84eb27'
            then:
              - lambda: |-
                  id(okno_roditeli).publish_state(false);

    # Окно кухня
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '351b2e'
            then:
              - lambda: |-
                  id(okno_kuhnya).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '351b27'
            then:
              - lambda: |-
                  id(okno_kuhnya).publish_state(false);

    # Окно санузел 1 этаж
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'bb20ae'
            then:
              - lambda: |-
                  id(okno_sanuzel_1_etaz).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'bb20a7'
            then:
              - lambda: |-
                  id(okno_sanuzel_1_etaz).publish_state(false);

    # Окно прихожая
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'bfab2e'
            then:
              - lambda: |-
                  id(okno_prihozaya).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'bfab27'
            then:
              - lambda: |-
                  id(okno_prihozaya).publish_state(false);

    # Окно крыльцо
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'dc5b2e'
            then:
              - lambda: |-
                  id(okno_krilco).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'dc5b27'
            then:
              - lambda: |-
                  id(okno_krilco).publish_state(false);	  

    # Окно санузел 2 этаж
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'be8b2e'
            then:
              - lambda: |-
                  id(okno_sanuzel_2_etaz).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'be8b27'
            then:
              - lambda: |-
                  id(okno_sanuzel_2_etaz).publish_state(false);	  

    # Окно спальня 1
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '50b2e'
            then:
              - lambda: |-
                  id(okno_spalnya_1).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '50b27'
            then:
              - lambda: |-
                  id(okno_spalnya_1).publish_state(false);	

    # Окно спальня 2
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'a7732e'
            then:
              - lambda: |-
                  id(okno_spalnya_2).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: 'a77327'
            then:
              - lambda: |-
                  id(okno_spalnya_2).publish_state(false);	

    # Окно детская
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '10d72e'
            then:
              - lambda: |-
                  id(okno_detskaya).publish_state(true);
         - if:
            condition:
              - text_sensor.state:
                  id: rf_code
                  state: '10d727'
            then:
              - lambda: |-
                  id(okno_detskaya).publish_state(false);		 

  - platform: version
    name: "Sonoff Rfbridge ESPHome Version"
    
  - platform: template
    name: Uptime Human Rfbridge
    id: uptime_human_rfbridge
    icon: mdi:clock-start

here is my second config:

esphome:
  name: sonoff_rfbridge
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: "xxx"
  password: "xxx"
  
api:
  password: "xxx"
  services:
    - service: send_rf_code
      variables:
        sync: int
        low: int
        high: int
        code: int
      then:
        - rf_bridge.send_code:
            sync: !lambda 'return sync;'
            low: !lambda 'return low;'
            high: !lambda 'return high;'
            code: !lambda 'return code;'
    - service: learn
      then:
        - rf_bridge.learn

uart:
  tx_pin: 1
  rx_pin: 3
  baud_rate: 19200

logger:
  baud_rate: 0

rf_bridge:
  on_code_received:
    then:
      - text_sensor.template.publish:
          id: rf_code
          state: !lambda 'char buffer [10];return itoa(data.code,buffer,16);'
      - homeassistant.event:
          event: esphome.rf_code_received
          data:
            sync: !lambda 'char buffer [10];return itoa(data.sync,buffer,16);'
            low: !lambda 'char buffer [10];return itoa(data.low,buffer,16);'
            high: !lambda 'char buffer [10];return itoa(data.high,buffer,16);'
            code: !lambda 'char buffer [10];return itoa(data.code,buffer,16);'

ota:
  password: "xxx"

web_server:
  port: 80

sensor:
        
#  WiFi Signal Sensor
#  Датчик отображающий уровень сигнала Wifi
  - platform: wifi_signal
    name: "Sonoff Rfbridge WiFi Signal"
    update_interval: 60s
    
#  Uptime Sensor

#  Датчик отображающий время работы
  - platform: uptime
    name: "Sonoff Rfbridge Uptime"
    id: sonoff_rfbridge_uptime
    update_interval: 60s
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human_rfbridge
            state: !lambda |-
              int seconds = round(id(sonoff_rfbridge_uptime).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? String(days) + "d " : "") +
                (hours ? String(hours) + "h " : "") +
                (minutes ? String(minutes) + "m " : "") +
                (String(seconds) + "s")
              ).c_str();

binary_sensor:

  - platform: template
    name: "Дверь входная"
    device_class: door
    lambda: !lambda |-
      if (id(rf_code).state == "d72f2e") {
        return true;
      } else if (id(rf_code).state == "d72f27") {
        return false;
      }

  - platform: template
    name: "Окно гостиная 1"
    device_class: door
    lambda: !lambda |-
      if (id(rf_code).state == "713b2e") {
        return true;
      } else if (id(rf_code).state == "713b27") {
        return false;
      }

  - platform: template
    name: "Окно гостиная 2"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "8cdb2e") {
        return true;
      } else if (id(rf_code).state == "8cdb27") {
        return false;
      }

  - platform: template
    name: "Окно родители"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "84eb2e") {
        return true;
      } else if (id(rf_code).state == "84eb27") {
        return false;
      }

  - platform: template
    name: "Окно кухня"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "351b2e") {
        return true;
      } else if (id(rf_code).state == "351b27") {
        return false;
      }

  - platform: template
    name: "Окно санузел 1 этаж"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "bb20ae") {
        return true;
      } else if (id(rf_code).state == "bb20a7") {
        return false;
      }

  - platform: template
    name: "Окно прихожая"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "bfab2e") {
        return true;
      } else if (id(rf_code).state == "bfab27") {
        return false;
      }

  - platform: template
    name: "Окно крыльцо"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "dc5b2e") {
        return true;
      } else if (id(rf_code).state == "dc5b27") {
        return false;
      }

  - platform: template
    name: "Окно санузел 2 этаж"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "be8b2e") {
        return true;
      } else if (id(rf_code).state == "be8b27") {
        return false;
      }

  - platform: template
    name: "Окно спальня 1"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "50b2e") {
        return true;
      } else if (id(rf_code).state == "50b27") {
        return false;
      }
  - platform: template
    name: "Окно спальня 2"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "a7732e") {
        return true;
      } else if (id(rf_code).state == "a77327") {
        return false;
      }

  - platform: template
    name: "Окно детская"
    device_class: window
    lambda: !lambda |-
      if (id(rf_code).state == "10d72e") {
        return true;
      } else if (id(rf_code).state == "10d727") {
        return false;
      }
    

text_sensor:
  - platform: template
    name: "Latest Code"
    id: rf_code

  - platform: version
    name: "Sonoff Rfbridge ESPHome Version"
    
  - platform: template
    name: Uptime Human Rfbridge
    id: uptime_human_rfbridge
    icon: mdi:clock-start

Maybe the problem is not in the code, but in the esphome version?

Some sensors that don’t work (it is mainly my front and back door, which are less than 10 feet away) are the ones that often fail, and always on close.

Thanks for the link on how to go with ESPHome. If I do this, is it also just as quick to go back if I want to?

@tman75: Only 2 options for your sensors really. Either the RF Bridge has trouble receiving or your sensors have trouble sending. I suggest you do some debugging. Could be interference, could be batteries, could be something I can’t think of right know…
I don’t know if flashing back to Tasmota is as easy as flashing ESPHome (from Tasmota). I already told you that your problem probably isn’t Tasmota. If you try ESPHome though, I also don’t see a reason to go back to Tasmota as the RF Bridge will probably work more or less the same with either firmware…

(ESPHome has the benefit of being well integrated into HA, both in communication as through the add-on. With ESPHome you can also handle sending/receiving of codes directly inside the firmware if you want. The firmware itself is also more optimized compared to Tasmota, which is like a big Swiss army knife)

You created template sensors with no template. So until you set their state, they don’t have one.

Did you somehow modify the Sonoff board? did you cut the tracks?

@samnewman86, you are probably talking about the first configuration option that I gave. There the template is substituted from the text sensor. In the second option, a template is set in the sensors, both options work in the same way, unsatisfactory.
@lordzid , no, traces are not cut off, I am using config via api and not via gpio

The problem was that esphome does not support Russian values in the name field.

Thanks for the examples on what your were using. Was able to get mine up and running as well based on that. Not sure if your sensors have low battery indicators like mine. Here is the additional for that. In my case the first 5 characters are the specific code and the 6th character “6” is for the battery alert. I need to think on best plan to reset the low battery alert.

  - platform: template
    name: "Front Door Battery"
    device_class: battery
    lambda: !lambda |-
      if (id(rf_code).state == "5CC906") {
        return true;
      } else {
        return false;
      }

I probably have the same 026 sensors, only before I did not know how to catch the code when the battery was low. I didn’t write the code for the tamper, because I plan to switch to zigbee and replace the window sensors. Since the last message, I have changed the new code for myself, and also added the battery status. When the battery trigger is triggered, then automation can be added. For example, I send a notification to a telegram. I attach a part of the code with 3 sensors.

  on_boot:
    priority: -10
    then:
      - binary_sensor.template.publish:
          id: dver_vkhodnaia_battery
          state: ON
      - binary_sensor.template.publish:
          id: okno_gostinaia_1_battery
          state: ON
      - binary_sensor.template.publish:
          id: okno_gostinaia_2_battery
          state: ON


rf_bridge:
  on_code_received:
    then:
      - homeassistant.event:
          event: esphome.rf_code_received
          data:
            sync: !lambda 'char buffer [10];return itoa(data.sync,buffer,16);'
            low: !lambda 'char buffer [10];return itoa(data.low,buffer,16);'
            high: !lambda 'char buffer [10];return itoa(data.high,buffer,16);'
            code: !lambda 'char buffer [10];return itoa(data.code,buffer,16);'

#Дверь входная
      - if:
          condition:
            lambda: |-
              return data.code == 0xD72F2E;
          then:
            - binary_sensor.template.publish:
                id: dver_vkhodnaia
                state: ON
      - if:
          condition:
            lambda: |-
              return data.code == 0xD72F27;
          then:
            - binary_sensor.template.publish:
                id: dver_vkhodnaia
                state: OFF
      - if:
          condition:
            lambda: |-
              return data.code == 0xD72F26;
          then:
            - binary_sensor.template.publish:
                id: dver_vkhodnaia_battery
                state: OFF
            - delay: 5s
            - binary_sensor.template.publish:
                id: dver_vkhodnaia_battery
                state: ON

#Окно гостиная 1
      - if:
          condition:
            lambda: |-
              return data.code == 0x713B2E;
          then:
            - binary_sensor.template.publish:
                id: okno_gostinaia_1
                state: ON
      - if:
          condition:
            lambda: |-
              return data.code == 0x713B27;
          then:
            - binary_sensor.template.publish:
                id: okno_gostinaia_1
                state: OFF
      - if:
          condition:
            lambda: |-
              return data.code == 0x713B26;
          then:
            - binary_sensor.template.publish:
                id: okno_gostinaia_1_battery
                state: OFF
            - delay: 5s
            - binary_sensor.template.publish:
                id: okno_gostinaia_1_battery
                state: ON

#Окно гостиная 2
      - if:
          condition:
            lambda: |-
              return data.code == 0x8CDB2E;
          then:
            - binary_sensor.template.publish:
                id: okno_gostinaia_2
                state: ON
      - if:
          condition:
            lambda: |-
              return data.code == 0x8CDB27;
          then:
            - binary_sensor.template.publish:
                id: okno_gostinaia_2
                state: OFF
      - if:
          condition:
            lambda: |-
              return data.code == 0x8CDB26;
          then:
            - binary_sensor.template.publish:
                id: okno_gostinaia_2_battery
                state: OFF
            - delay: 5s
            - binary_sensor.template.publish:
                id: okno_gostinaia_2_battery
                state: ON


binary_sensor:
#Дверь входная
  - platform: template
    name: 'dver_vkhodnaia'
    id: dver_vkhodnaia
    device_class: door
  - platform: template
    name: 'dver_vkhodnaia_battery'
    id: dver_vkhodnaia_battery
    device_class: power
#Окно гостиная 1
  - platform: template
    name: 'okno_gostinaia_1'
    id: okno_gostinaia_1
    device_class: window
  - platform: template
    name: 'okno_gostinaia_1_battery'
    id: okno_gostinaia_1_battery
    device_class: power
#Окно гостиная 2
  - platform: template
    name: 'okno_gostinaia_2'
    id: okno_gostinaia_2
    device_class: window
  - platform: template
    name: 'okno_gostinaia_2_battery'
    id: okno_gostinaia_2_battery
    device_class: power
2 Likes

This might be a bit of a n00b question in this thread, but information is hard to find. (on the current version of ESPhome)

Once I have it flashed with ESPhome and added into homeassistant.

How exactly do you sniff codes?
What codes can be sniffed with the OEM software on the secondary rf chip?

I have a window sensor here, once I sniff the code, I assume I add a binary sensor in the ESPhome config for the sonoff RF

I found I could only sniff via tasmota, the esphome commands such as rf_bridge.on_advanced_code_received and rf_bridge.start_advanced_sniffing didn’t work for me.

Alright after some testing

(No hardware hack, stock firmware on the RF chip)

You go to the logs (via either web portal or ESPhome addon) and it should automatically be logging any RF codes coming in.

Fell into the trap of the sonoff DW2-RF only sends codes when magnet is removed from sensor. (like seriously who programs useless things like this.)

Wait - but that sonoff DW2-RF is a door/window sensor. Isn’t that by design?
I, for one, would like my door sensor to send signals only when the magnet goes on (from off) or off (from on), as opposed to sending RF pulses constantly.

After doing some searching on the web, there is quite a few that don’t transmit on and off.

I’m sure there are some other use for that logic.
But I would not buy any door/window sensor that does not transmit on/off. Just saying.

Yup agree, I had no idea until I was troubleshooting it.

Will be door to hackup for a door bell however

I struck this a couple of years back, caused all sorts of grief. The fix was to set the binary sensor to reset via an automation after a few seconds.
If you try the cheap Digoo 433Mhz sensors you should find they send both open and close codes (and battery low).

They are already on the way LOL

Hi Guys,

I am using a Sonoff RF bridge with esphome and Portisch firmware.
I receive the raw rf codes and basically it works fine and I use binary sensors defined like this:

  - platform: remote_receiver
    name: "OpenClose1_Opened"
    internal: true
    rc_switch_raw:
      code: '100101011111001000001010'
      protocol: 2
    on_press:
      then:
        - switch.turn_on: open_close_1
    filters:
      - delayed_off: 5s

  - platform: remote_receiver
    name: "OpenClose1_Closed"
    internal: true
    rc_switch_raw:
      code: '100101011111001000001110'
      protocol: 2
    on_press:
      then:
        - switch.turn_off: open_close_1
    filters:
      - delayed_off: 5s

to detect signals from my sensors.

but its network connection is unstable so my sensors go unavailable quite often.
This could be caused by the amount of code /sensors defined in the esphome code.

I am trying to use the “rf_bridge” “on_code_received” and fire a home assistant event i order to move all logic to home assistant automations.

uart:
  tx_pin: 1
  rx_pin: 3
  baud_rate: 19200

logger:
  baud_rate: 0
  
rf_bridge:
  on_code_received:
    then:
      - homeassistant.event:
          event: esphome.rf_code_received
  on_advanced_code_received:
    then:
      - homeassistant.event: 
          event: esphome.rf_code_received

But to some reason on_code_received and on_advanced_code_received are not triggered and therefor I am not able to do any automation in Home assistant when code is received.

I added firing esphome.rf_code_received from one of my binary sensors

  - platform: remote_receiver
    name: "catch  All"
    id: catchall
    internal: true
    rc_switch_raw:
      code: '110001000100000000110000'
    on_press:
      then:
        homeassistant.event:
          event: esphome.rf_code_received
    filters:
      - delayed_off: 5s   

it works and succeeded triggering an automation in home assistant.

But I need a generic way for all codes and not do such logic for each specific code
So it is not the way I fire the event that is the problem.

But why is on_code_received not triggered?
could it be because I am receiving the raw codes instead?
Any idea how I can switch to receiving Hex codes?
is there a way of defining a generic binary sensor for alle codes, by wildcards for example?

I ma really stuck in this and hope somebody can help me out

thanks :slight_smile: