Posts Making a dumb light switch smart with ESPHome and Home Assistant
Post
Cancel

Making a dumb light switch smart with ESPHome and Home Assistant

Project: Smart light switch with offline fail-over

Goals

  1. Create a light switch that is decoupled from power delivery so the 9 Hue Bulbs in my Dining Room Chandelier can always be powered, while allowing use of the light switch on/off paddle.
  2. Provide a fail-over mechanism that allows the switch to operate even when Home Assistant is unavailable.

Purchased Supplies

  1. Shelly1 (or a Sonoff Basic, or other ESPHome compatible board).
  2. Electrical wire (Romex 12/2, solid wire, 2 covered conductors plus one ground conductor).
  3. Wire Nuts, Non-twist Connectors, or Wago Connectors.

The above links include my Amazon Affilite id.

Goal #1: Make the dumb light switch talk to Home Assistant

I started with the following ESPHome code fragment which uses the Home Assistant API to toggle the smart bulbs on or off when the wall switch is flipped. This worked great and I could have stopped there. But I want to make it work if Home Assistant wasn’t available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO5
    name: Wall Switch
    id: button
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_state:
      - homeassistant.service:
          service: light.toggle
          data:
            entity_id: light.dining_room

switch:
  platform: gpio
  id: relay
  pin: GPIO4
  restore_mode: ALWAYS_ON

Goal #2: Fail-over

So, we need a way to check to see if Home Assistant is connected, so we can toggle the light with the relay instead. Luckily ESPHome provides a condition for checking if Home Assistant is connected: api.connected.

1
2
3
4
if:
  condition:
    api.connected:
  then:

Next, we check to see if the relay is on, and if it is off turn it on. We need the relay to be on before Home Assistant can turn on our smart bulbs on.

Note

In theory the relay should always be on. However there is one scenario, which will be revealed soon, in which the relay would be off.

1
2
3
4
5
6
7
8
9
10
    - if:
        condition:
          switch.is_off: relay
        then:
          - switch.turn_on: relay

          - homeassistant.service:
              service: light.turn_on
              data:
                entity_id: light.dining_room

If the relay is already on then ask Home Assistant to toggle the light on or off.

1
2
3
4
5
6
    else:
      - homeassistant.service:
          service: light.toggle
          data:
            entity_id: light.dining_room

Now we come to the “fail-over” bit. This is the else condition for when api.connected is false, meaning that ESPHome has lost connection to Home Assistant!

1
2
else:
  - switch.toggle: relay

This code fragment simply turns the Shelly1’s internal relay from on to off or off to on when the physical light switch is toggled.

Final Code

If you have ever done programming before you know may be aware a common practice is to define “constant” variables at the top of your code. Well, that is what ESPHome’s substitutions feature provides.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
---
# Shelly 1 Power Module
# Location: Dining Room Light Switch
#
substitutions:
  project: Shelly1 01
  id: shelly1_01
  button_gpio: GPIO5
  relay_gpio: GPIO4
  hass_light: light.dining_room

esphome:
  name: $id
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_pass

ota:

logger:

# Home Assistant API
api:

script:
  - id: hass_light_toggle
    then:
      if:
        condition:
          api.connected:
        then:
          - if:
              condition:
                switch.is_off: relay
              then:
                # Turn the relay back on and turn on the light.
                - switch.turn_on: relay

                - homeassistant.service:
                    service: light.turn_on
                    data:
                      entity_id: $hass_light
              else:
                # Have Home Assistant toggle the light.
                - homeassistant.service:
                    service: light.toggle
                    data:
                      entity_id: $hass_light
        else:
          # When HA is unavailable, toggle the relay.
          - switch.toggle: relay

binary_sensor:
  - platform: gpio
    pin:
      number: $button_gpio
    name: $project Wall Switch
    id: button
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_state:
      - script.execute: hass_light_toggle

switch:
  platform: gpio
  id: relay
  pin: $relay_gpio
  restore_mode: ALWAYS_ON

It’s not a bug, its a feature

The relay can only be turned off when Home Assistant is offline when the light was turned off by the wall switch. So, when Home Assistant comes back online that smart light will be unavailable until the wall switch is flipped again.

Let’s call this an intended side-effect. If we made the relay somehow turn back on automatically when it connects to Home Assistant again, the smart bulb would turn on! I can tell you from experience wives really don’t like your Home Automation hobby when the bedroom lights turn on in the middle of the night!

Special Thanks

Thank you to Mauricio Bonani (@mbonani) of bonani.tech for encouraging me to create a blog as a knowledge dump that I can refer back to in the future. I hope others find some of my articles as useful and I have found Mauricio’s articles.

Feedback

Thank you for visiting my new blog! This is my first article, and I would really appreciate your feedback. Please stick around as I will be posting articles at least once a week for the next few months. I already have ideas set aside for 29 more articles on Home Assistant and ESPHome, not to mention potential tips on creating designs for laser cutters!

To hold you until my next article please visit my ESPHome Github Repository.