Fall back to relay if not connected to HA

I’ve managed to implement the fallback using the amazing ping sensor, which is an external component by trombik. I use it to regularly ping Home Assistant from the ESP. The sensor exposes two values: latency and packet loss. When flipping the wall switch, I simply check if the packet loss is 100%. If it is, something must be amiss and it falls back to the relay instead.

It’s not a pretty solution and there are some downsides, but it works well enough for me. I can tweak the number of pings and the interval. More pings take more time but make false positives less likely. If I set the interval too short, I’m pinging a lot, which can become a problem if I have many devices doing this, though I don’t expect to run into this.

Shelly 1L config with fallback mode
substitutions:
  device_name: kitchen

# Basic Config
esphome:
  name: ${device_name}
  platform: ESP8266
  board: esp01_1m
  libraries:
    - ESP8266WiFi
    - https://github.com/akaJes/AsyncPing#95ac7e4

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: ${device_name}
    password: !secret wifi_password

logger:
api:
ota:

web_server:
  port: 80
  
external_components:
  - source: github://trombik/esphome-component-ping
    components: [ ping ]

#==============================================================
switch:
  - platform: gpio
    pin: GPIO5
    id: shelly_1l_relay
    restore_mode: ALWAYS_ON

binary_sensor:
  - platform: gpio
    name: ${device_name} Input
    pin:
      number: GPIO4
    # small delay to prevent debouncing
    filters:
      - delayed_on_off: 50ms
    on_state:
        then:
          - if:
              condition:
                and:
                  - wifi.connected:
                  - api.connected:
                  - switch.is_on: shelly_1l_relay
                  - lambda: return id(packet_loss).state < 100;
              # toggle smart light if wifi and api are connected and relay is on
              then:
                # - switch.toggle: shelly_1l_relay
                - logger.log:
                    format: "Packet loss '%.1f'"
                    args: [ 'id(packet_loss).state' ]
                - homeassistant.service:
                    service: light.toggle
                    data:
                      entity_id: light.kitchen_lights
              # else, toggle relay
              else:
                - switch.toggle: shelly_1l_relay
    id: button

sensor:
  - platform: ping

    # IP address of Home Assistant
    ip_address: 192.168.178.22

    # number of packets to send
    num_attempts: 5

    # the timeout. however, this is not what you usually expect from `ping`
    # implementation: the timeout is also the interval to send packets. if you
    # set this value to 10 sec, and the network is fine (no packet loss), then
    # the component sends a packet at 10 sec interval, and the total time to
    # finish would be 10 sec * num_attempts = 10 * 17 = 170 sec.
    timeout: 1sec

    loss:
      # the name to be shown.
      id: packet_loss
      name: Packet loss

    latency:
      # the name to be shown.
      id: latency
      name: Latency
      # this should be 3 as the value is float, unit is sec, and the raw
      # values are in ms.
      accuracy_decimals: 3

    # the interval for checking the sensors. defaults to 60s.
    update_interval: 10s

status_led:
  pin: GPIO0

Note that ping depends on two additional libraries, which are included in the first block.

To make the fallback mode complete, I’ve configured my Zigbee smart bulbs to turn on by default after loss of power. This ensures that if a bulb is ‘soft off’ (powered, but shut off by HA) and a problem occurs, I can take the power off using the wall switch (utilizing the Shelly in fallback mode) and then on again, which will turn the light on (since that’s the default).

I’m pretty confident this will enable me to use my lights as long as I have power :grin: Let me know if this was useful to any of you!

4 Likes