For a while now, I’ve been automating my apartment using the automations component of Home Assistant. In fact, I had amassed quite the collection of automations and was starting to have a problem keeping track of them all and their various interactions (intentional or otherwise). So earlier this year when Home Assistant introduced automation debugging I decided to sit down and refactor the whole thing.
At first, I considered deploying and using MQTT which, it seems, a lot of Home Assistant users do. However, I wasn’t overly excited at running another container or at learning Yet Another Thing. Likewise, I considered Node-RED and discarded it too. I’m probably making things harder for myself by sticking to editing YAML in Vim but I knew my needs weren’t overly complicated and by sticking to ’the basics’ I knew it would force me to stop being overly-clever and make something that Just Works™. So I sat down with the new debugging tool, wrote out all of my ‘what do i want automated’ needs, and pored back over the automation documentation.
And that’s when I realized that a timer was the component I’d been overlooking all this time. Timers, it turns out, can be used very much in an MQTT-lite fashion. You see, you can have one or more routines triggered by the same timer; in fact, some set of routines can listen for timer (re)start and another set can listen for timer finish/idle. Mix-n-match these up and you can make some very interesting actions happen. And it means my automations each generally do one thing and only one thing (KISS) which, in turn, means they are less likely to fail and easier to debug when they do. I was stoked! I was also annoyed at not having paid any attention to timers from the get-go, but what are you gonna do?
My first task was thinking about what timers I’d need. I knew right away I’d want
a timer.away
for when I leave home:
timer:
away:
duration: 00:05:00
But what other timers do I need? I quickly realized that I need a timer for
almost every switch I have defined in Home Assistant. I could get away with
fewer, but I allowed myself a little bit of cleverness and created one for
each switch with the name of the timer being the name of the switch it
controls. So, for example, I have a TP Link Kasa smart switch controlling my
hallway light called switch.hallway_light
. So I created a matching timer
called timer.switch_hallway_light
. This allows me to to write a simple
automation like this:
- alias: Trigger - Start light switch trigger
id: '1625266493'
description: 'When a light turns on, start its corresponding power off trigger'
trigger:
- platform: state
entity_id: switch.bar_light
to: 'on'
- platform: state
entity_id: switch.closet_light
to: 'on'
- platform: state
entity_id: switch.dining_room_light
to: 'on'
- platform: state
entity_id: switch.entryway_light
to: 'on'
- platform: state
entity_id: switch.hallway_light
to: 'on'
condition: []
action:
- service: timer.start
data:
duration: '0:10:00'
target:
entity_id: "timer.{{ trigger.entity_id.split('.')|join('_') }}"
What this does is exactly what it says in the description. Whenever one of the
lights in the trigger
section turns on, it starts the corresponding timer.
The magic is in the very last line of the automation:
entity_id: "timer.\{\{ trigger.entity_id.split('.')|join('_') \}\}"
What we’re doing here it taking the entity id that fired the automation (e.g.
what switch did we turn on) from the trigger.entity_id
value then we
swap out the .
for a _
which gives us the name of our timer. So here we
have one automation, that does one very simple thing which makes it kinda hard
to break this automation.
So we’ve turned on the hallway light, and started our timer. What happens when the timer runs out? Well, we have an automation that is triggered by that:
- alias: Trigger - Kill the lights
id: '1625267293'
description: 'When a timer runs out, kill its corresponding light'
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.switch_bar_light
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.switch_closet_light
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.switch_dining_room_light
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.switch_entryway_light
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.switch_hallway_light
condition: []
action:
- service: homeassistant.turn_off
target:
entity_id: "switch.\{\{ trigger.event.data.entity_id.split('_')[1:4]|join('_') \}\}"
As you can see, it’s basically the opposite of the previous automation. We list which timers we care about, and when they finish, we munge the timer name a bit to get the switch’s name and then we turn that switch off. Simplicity.
Hopefully, you can see the utility of timers in Home Assistant. This is just a very basic example of how I use them, but I think it illustrates their user pretty well. I still have just over 50 automations, but that’s way down from what I had, and the automations themselves are now way simpler. Overall, I consider this a win.
Happy hacking!