We recently built a new house and boy howdy does it have a lot more doors and locks than our old house. And now that my kids are getting older they tend to leave doors unlocked / ajar and we’ve left via the garage one too many times with something unlocked. Now, I have alerts in Home Assistant that tell me when this happens after I leave home, but sometimes that’s not good because I’ve had locks jam or doors not be closed all the way so they can’t be locked remotely. To solve this, I designed and built a lite-up box that mounts to our garage wall that shows the status of all the locks and doors before we leave.
Mounted to the wall
I neglected to take a photo on the wall when it was on, so here’s one from my bench.
The design is very simple, it’s eight WS2812B addressable LEDs in series hooked up to a WeMos D1 Mini with the WeMos powering the LEDs via its 5v pin. These are then hot glued into a 3d printed case.
(Not pictured, the 330 ohm resistor on the data line that I added afterwards)
This is the flashed with ESPHome to turn on the LEDs when the garage door is opened, check all locks and doors and change the color of the light from green to red if the sensor is in a “bad” state.
substitutions:
device_name: garage-door-alert
front_lock: "6"
front_status: "7"
back_lock: "1"
back_status: "0"
interior_lock: "4"
interior_status: "5"
exterior_lock: "3"
exterior_status: "2"
esphome:
name: ${device_name}
platform: ESP8266
board: d1_mini
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pass
ap:
ssid: Fallback ${device_name}
password: "hackme"
captive_portal:
# Enable Home Assistant API
api:
ota:
script:
- id: turn_on_lights
then:
- logger.log: 'Turning on lights'
- light.turn_on:
id: door_alert
brightness: 1
red: 0
green: 0
blue: 1
- id: turn_off_lights
then:
- logger.log: 'Turning off lights'
- light.turn_off: door_alert
- id: change_lights
mode: queued
then:
- logger.log: 'Changing lights'
- light.addressable_set:
id: door_alert
range_from: ${front_lock}
range_to: ${front_lock}
red: !lambda "return (id(sensor_front_lock).state == \"locked\") ? 0 : 255;"
green: !lambda "return (id(sensor_front_lock).state == \"locked\") ? 255: 0;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${back_lock}
range_to: ${back_lock}
red: !lambda "return (id(sensor_back_lock).state == \"locked\") ? 0 : 255;"
green: !lambda "return (id(sensor_back_lock).state == \"locked\") ? 255: 0;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${interior_lock}
range_to: ${interior_lock}
red: !lambda "return (id(sensor_interior_lock).state == \"locked\") ? 0 : 255;"
green: !lambda "return (id(sensor_interior_lock).state == \"locked\") ? 255: 0;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${exterior_lock}
range_to: ${exterior_lock}
red: !lambda "return (id(sensor_exterior_lock).state == \"locked\") ? 0 : 255;"
green: !lambda "return (id(sensor_exterior_lock).state == \"locked\") ? 255: 0;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${front_status}
range_to: ${front_status}
red: !lambda "return (id(sensor_front_status).state) ? 255 : 0;"
green: !lambda "return (id(sensor_front_status).state) ? 0: 255;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${back_status}
range_to: ${back_status}
red: !lambda "return (id(sensor_back_status).state) ? 255 : 0;"
green: !lambda "return (id(sensor_back_status).state) ? 0: 255;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${interior_status}
range_to: ${interior_status}
red: !lambda "return (id(sensor_interior_status).state) ? 255 : 0;"
green: !lambda "return (id(sensor_interior_status).state) ? 0: 255;"
blue: 0
- light.addressable_set:
id: door_alert
range_from: ${exterior_status}
range_to: ${exterior_status}
red: !lambda "return (id(sensor_exterior_status).state) ? 255 : 0;"
green: !lambda "return (id(sensor_exterior_status).state) ? 0: 255;"
blue: 0
text_sensor:
- platform: homeassistant
id: sensor_door_garage_main
entity_id: cover.door_garage_main
on_value:
then:
- if:
condition:
text_sensor.state:
id: sensor_door_garage_main
state: 'open'
then:
- script.execute: turn_on_lights
else:
- script.execute: turn_off_lights
- platform: homeassistant
id: sensor_front_lock
entity_id: lock.door_front
on_value:
then:
- script.execute: change_lights
- platform: homeassistant
id: sensor_back_lock
entity_id: lock.door_back
on_value:
then:
- script.execute: change_lights
- platform: homeassistant
id: sensor_interior_lock
entity_id: lock.door_garage_interior
on_value:
then:
- script.execute: change_lights
- platform: homeassistant
id: sensor_exterior_lock
entity_id: lock.door_garage_exterior
on_value:
then:
- script.execute: change_lights
binary_sensor:
- platform: homeassistant
id: sensor_front_status
entity_id: binary_sensor.door_front
on_state:
then:
- script.execute: change_lights
- platform: homeassistant
id: sensor_back_status
entity_id: binary_sensor.door_back
on_state:
then:
- script.execute: change_lights
- platform: homeassistant
id: sensor_interior_status
entity_id: binary_sensor.door_garage_interior
on_state:
then:
- script.execute: change_lights
- platform: homeassistant
id: sensor_exterior_status
entity_id: binary_sensor.door_garage_exterior
on_state:
then:
- script.execute: change_lights
light:
- platform: fastled_clockless
chipset: WS2812B
rgb_order: GRB
pin: GPIO14
num_leds: 8
name: "Door Alert"
id: door_alert
internal: true
on_turn_on:
- delay: 2s
- script.execute: change_lights
If anyone is interested, I can clean up the FreeCAD design and provide STLs for all the parts.
Big thanks to @oxan for helping me with my issue calling address_set from a lambda that took this code from hideous to only terrifying.