If you want simple motion-controlled lights, this will be overkill.
My goal was for lights (or anything else, but I’ll just call them lights) to be automated by motion, or doors opening (or anything else), which a non-technical person can easily override e.g. if they want a light to stay on, no automation will turn it off
I also want my automations to control groups of lights and for any light to be in any number of groups e.g. the porch light and floodlights come on if someone rings the doorbell at night, but the porch light and the foyer light come if you open the door
To make this work I created a timer for each light that I want to automate. To simplify templates, each timer uses the same name as its light e.g. switch.hall_light
and timer.hall_light
Timers are implicit when you turn-on
something for
some period of time, but making them explicit gives us more control
Three automations do most of the work (code is below)
- Whenever a timer is started, an automation turns on its light
- whenever a timer is finished, an automation turns off its light
- Whenever a light goes off, an automation cancels its timer
Whenever a trigger occurs, (door is opened, alarm goes off, arrive home, motion sensed etc,) all I need to do is start timers for whatever lights I want to control. Each trigger can set different times for different lights. (I also have a rarely-needed override on my App that allows me to change the mode of any trigger to either: always, night-only, or off)
Triggers follow a few rules
A If the light is off, start a timer for it (and Automation 1 will turn it on)
B If the light is on with a timer running, extend the timer
C If the light is on with no timer running, do nothing
Rule C allows anyone to override any light just by turning it on (if it’s already on, they first turn it off (which kills the timer) then on which prevents it from being controlled by any automation
Manually controlling the light can be done with a wall switch, or with the app or voice control. The app and voice control are programmed to automatically turn off the light before it is turned on which (if it was already on) provides a nice blink so someone knows they have taken control of the light
On my app, the button for each light also shows the remaining time on its timer (if any) which lets anyone know if that light is on by automation or because someone turned it on
That’s it. Below is my code for the three automations. This could be improved to allow different domains (all my lights are switches, so I don’t have code for the light domain)
My triggers are mostly in Node Red, but anything should work if you follow the three rules.
- alias: "Timer Finished to Switch"
mode: parallel
trigger:
- platform: event
event_type: timer.finished
action:
- service: switch.turn_off
data:
entity_id: "switch.{{ trigger.event.data.entity_id.split('.')[-1] }}"
- alias: "Timer Started to Switch"
mode: parallel
trigger:
- platform: event
event_type: timer.started
action:
- service: switch.turn_on
data:
entity_id: "switch.{{ trigger.event.data.entity_id.split('.')[-1] }}"
- alias: "Switch State to Cancel Timer"
mode: parallel
trigger:
- platform: state
to: "off"
entity_id:
- switch.office_credenza
- switch.office_desk
#
# etc. for every light that is automated
# (for the state platform, I believe I need to # specify each entity id in the trigger
# please correct me if I'm wrong)
#
action:
- service: timer.cancel
data:
entity_id: "timer.{{ trigger.to_state.entity_id.split('.')[-1] }}"