Disclosure: This article may contain affiliate links. If you decide to make a purchase, I'll make a small commission at no extra cost to you.
Project: Smart light switch with offline fail-over
Goals
- 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.
- Provide a fail-over mechanism that allows the switch to operate even when Home Assistant is unavailable.
Purchased Supplies
- Shelly1 (or a Sonoff Basic, or other ESPHome compatible board).
- Electrical wire (Romex 12/2, solid wire, 2 covered conductors plus one ground conductor).
- Wire Nuts, Non-twist Connectors, or Wago Connectors.
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.