Simplifying Automations

Mon 05 June 2023

Since a couple of months I'm using Home Assistant. I've been using a VeraEdge home controller for years, to control my zwave devices, but the last year or two the support for that device was failing (especially the cloud storage for security cam images was buggy, to say the least): since they started promoting Ezlo I knew why, and I decided not to go that way.

Luckily for me, Home Assistant integrates perfectly with VeraEdge (and doesn't with Ezlo, yet?) so that was a win-win. In the meantime I've expanded my collection with several ZigBee devices.

After creating several automations I realized that nothing worked like it should, or at least I got unpredicable results (like lights that flashed on when motion detected, and went out after a second, while they should be on for at least one minute after motion cleared again).

Also, things got more complicated for other lights as well, take for instance my lights in the living room:

  • they should go on at 4:50 AM on work days, except when vacation mode is on
  • they should go on in the evening, based on the lights outside, when someone is at home
  • they should go on when the first on arrives at home, only in the evening
  • they should go on when someone presses a ZigBee button

and for the off-states:

  • they should go off when someone presses the same ZigBee button
  • they should go off when then sun is bright enough
  • they should go off when the last one leaves the house
  • they should go off when receiving an 'all lights off' command

Off course, lights should only be turned off when they are on, and lights should only be turned on when off.

These requirements lead to either one massive automation with lots of if-s, choices, and what have you, or lead to multiple automations with repeating actions and conditions. And neither of them are a workable solution for me. The solution was to split everything up in atomic pieces, and use the eventbus of Home Assistant extensively.

In short: sensors publish an event, actuators trigger on events. There's an automation for individual states of sensos/actuators.

This might sound like a lot of work to set up (which it is), but makes maintenance so much easier.

As an example, consider a motion sensor, and a porch light. The way that most people set this up is:

- trigger
    - detect motion
- condition:
    - check if light is off
    - check if sun is below horizon
- action:    
    - porch light on
    - wait for motion clear (for a certain amount of time)
    - porch light off

This would be one automation, which makes perfectly sense. In my case I would have (at least) 4 automations:

  • motion on
  • motion off
  • porch light on
  • porch light off

"Motion On" would look like:

- trigger:
    - motion detected
- action: 
    - event: motion_on

"Porch light On":

- trigger: 
    - event: motion_on
- condition:
    - check if porch light is off
    - check if sun is below horizon
- action: 
    - switch light on

"Motion Off":

- trigger:
    - motion cleared
        for: 1 minute
- action:
    - event: motion_off

"Porch Light Off:

- trigger:
    - event: motion_off
- action:
    - switch light off

Why, do you ask? The conditions about lights on/sun down have nothing to do with the motion detection, only with the light. Things become even more complicated if you want to take a snapshot with your security cam of the one triggering the motion, day or night.

In the traditional way, this looks somehow like this:

- trigger:
    - detect motion
- action:
    - take snapshot
    - if sun below horizon:
        - check if light is off
        - turn porch light on
        - wait for motion clear
        - turn porch light off

While in my case, I just add another automation:

"Take Snapshot":

- trigger:
    - event: motion_on
- action:
    - take snapshot

In my case, I even went a step further with the "Porch Light On" automation: The various checks are left out of this automation, and are in a 'central' "Lights On" automation:

"Porch Light On":

- trigger:
    - event: motion_on
- condition:
    - sun below horizon
- action:
    - event: light_on
        - event_data: entity_id: light.porch_light

And then for the "Lights On" automation (which is a good use case for running automations in parallel mode :) )

- trigger:
    - event: light_on
- condition:
    - light is off
- action:
    - switch on {{ entity_id }}

The latter automation is a bit more complicated in real life, since I use light-entities, but also switch-entities to switch on/off lights.

Taking this back to my living room use case: I have three different lights listening for events for turning them on. These events are created by different automations (showing two):

"Workdays":

- trigger:
    - time equal to 4:50
- condition:
    - work days
    - not vacation
- action:
    - event: wake_up_lights

"Lights On Evening":

- trigger:
    - sun below certain point
- condition:
    - occupation > 0
- action:
    - event: lights_on_evening

The three lights trigger on:

- trigger:
    - event: wake_up_lights
    - event: lights_on_evening
    - event: welcome_home_lights
    - event: ikea_switch_on
    - event: all_lights_on
- action:
    - event: light_on

etcetera.

I have one automation that sends an event when the outside light is bright enough, those same three lights listen for those events in their "Lights Off" automation, but also the lights in the attic.

One automation controls them all :)

By peter, Category: homeautomation