Automations


Home > My Projects > Home Automation > Automations

Automations, or more properly the ability to create and use automations, are somewhat the entire point of all this effort. My ultimate goal is to have to manually interact with the house as little as possible, whenever possible. As my system is still in development and will be for the foreseeable future I can't yet reach that nirvana but I have developed automations I find extremely useful and convenient. I'll share those below as I'm sure others will find utility in them as well.

Just a note that the code I provide here will include the necessary components of the automation, however I'm not going to include everything. For example, if the automation is to turn a light off after a timer expires I will only provide the code defining the timer and the automation. The light entity is irrelevant since it matters not what type of light it is (ie. MQTT), only that it exists and responds to HA service calls.

You're also not going to find any "fluff" here. And I define "fluff" (at certainty of offending some) as cutsie automations created just because one can. Or anything to do with media as I've not reached that point in the system yet, nor will I care much past "Basement Lights Watch TV Mode" when I do.

Lights On At Dusk With Random Off

This is the standard "turn my lights on at dusk" which is probably the first automation anyone creates. So why would I share it? Only reason is because of the little twist of the semi-random turn off time. Turn off takes place at any point within a set period randomly chosen between 11:05PM and 11:30PM. This is accomplished via a delay action using a template to generate a timestamp with the minutes and seconds values randomly chosen within the appropriate ranges.

I use this same automation for multiple exterior lights which adds a bit of variation and more naturally simulates a person turning off the lights.

automations.yaml:

##################PORCH LIGHT
automation:
####PORCH LIGHT ON AT DUSK
  - id: '1525226771173'
    alias: Porch Light On At Dusk
    trigger:
    - event: sunset
      platform: sun
    condition: []
    action:
    - data:
        entity_id: light.porch_light
      service: homeassistant.turn_on
####PORCH LIGHT OFF RANDOMLY BETWEEN 11:05PM AND 11:30PM
  - id: '1525226960239'
    alias: Porch Light Off After 11PM
    trigger:
    - at: '23:00:00'
      platform: time
    condition: []
    action:
    - delay: '00:{{ ((range(5,30)|random)|int) ~":" ~ ((range(5,55)|random)|int) }}'
    - data:
        entity_id: light.porch_light
      service: homeassistant.turn_off

Automatic Lighting On Door Open With Timer & Motion Reset

This is one of my go-to automations for automatic lights that are triggered by room entry. I extensively use variations of this all over the house and it form the basis of my automatic lighting. This particular automation turns on my "Shop Fab Lights". As the fabrication area ("fab") of my shop is where my tools live, there are many times I am running from the house to the shop for a tool and expect an illuminated tool selection experience.

In order for this to work, a timer is required. This will set the initial duration for which the lights are on.

configuration.yaml:

timer:
  shop_entry_lights:
    duration: '00:05:00'

The functionality of this automation is actually made up of several automations. I realize I could probably consolidate this a little, however it is a lot easier to troubleshoot separate automations versus an enormous automation using multiple templates to make decisions as to which part of it will run. Maybe some people prefer to "elegantly" combine all these decisions into one automation. I don't mind extra automations, each serving a single function.

automations.yaml:


#######################SHOP AUTOMATIC FAB LIGHTS ON 5 MINUTES AT ENTRY 
  - id: '1539021689151'
    alias: Shop Automatic 5 Minutes Lights On Entry
    trigger:
    - entity_id: binary_sensor.shop_man_overhead_doors
      from: 'off'
      platform: state
      to: 'on'
    condition:
    - condition: state
      entity_id: person.aaron
      state: home
    - condition: state
      entity_id: light.shop_fab_light
      state: 'off'
    - condition: state
      entity_id: light.shop_light_north
      state: 'off'
    - condition: state
      entity_id: light.shop_light_south
      state: 'off'
      #Only trigger if entering shop, not exiting
    - condition: state
      entity_id: binary_sensor.shop_interior_motion
      state: 'off'
    action:
    - data:
        entity_id: light.shop_fab_light
      service: homeassistant.turn_on
    - data:
        entity_id: timer.shop_entry_lights
      service: timer.start

This first automation triggers the light (light.shop_fab_light) when the shop door is opened (binary_sensor.shop_man_overhead_doors). When the state of this sensor transitions from "off" (which represents closed) to "on" the automation is triggered. It then checks via conditions that all of the shop lights are turned off. Because if there are shop lights already turned on, it stands to reason I am already in the shop and I don't want this automation to fire which will redundantly turn on the "fab room" light and set the timer to turn it off later. The condition stipulating that binary_sensor.shop_interior_motion must be in state "off" (no motion detected) is key as well because it prevents this automation from turning lights on if I am leaving the shop. If there is interior motion and I open the door, I am leaving. If there is no interior motion and I open the door, it is reasonable that I am entering. Additionally many of these automations only trigger if I am home (person.aaron is in state "home", the first condition) because I want a different behaviour if the shop door is opened when I'm not home (it should never be opened when I am not home).

After all of those conditions defining when the automation should fire have evaluated, the action is relatively simple. Call the service homeassistant.turn_on to turn on "light.shop_fab_light". And importantly, call the timer.start service to start the "timer.shop_entry_lights" timer.

As timer.shop_entry_lights has a 5 minute cycle, that is the minimum amount of time the shop fab lights will be on. When the timer has run out, an automation to turn off the lights is triggered.

automations.yaml:

  - id: '1539022015932'
    alias: Shop Entry Automatic 5 Minute Lights Timeout (Turn Off)
    trigger:
    - event_data:
        entity_id: timer.shop_entry_lights
      event_type: timer.finished
      platform: event
    condition: []
    action:
    - data:
        entity_id: light.shop_fab_light
      service: homeassistant.turn_off
    - data:
        entity_id: light.shop_light_north
      service: homeassistant.turn_off
    - data:
        entity_id: light.shop_light_south
      service: homeassistant.turn_off

Triggering on the "timer.finished" event raised by timer.shop_entry_lights, this simply calls homeassistant.turn_off for all shop light entities (could have been a list under one single entity_id). All shop lights are turned off because I might turn on another light upon entry or during my temporary time in the shop, and I'd want those to automatically turn off as well.

Next, an automation to reset the timer if the shop interior motion sensor (actually several sensors combined) is triggered.

automations.yaml:

#######RESET THE TIMER ON MOTION
  - id: '1539084370287421689151'
    alias: Shop Automatic 5 Minutes Motion Timer Reset
    trigger:
    - entity_id: binary_sensor.shop_interior_motion
      from: 'off'
      platform: state
      to: 'on'
    condition:
    - condition: state
      entity_id: timer.shop_entry_lights
      state: 'active'
    action:
    - data:
        entity_id: timer.shop_entry_lights
      service: timer.start

Because the most annoying thing in the world (maybe I am slightly exaggerating) is to experience unexpected delumination at the wrong time due to a motion light timer expiring. I think we've all been in a public restroom to experience this exact circumstance. This automation fires upon a state change of binary_sensor.shop_interior_motion and if timer.shop_entry_lights is active, calls service timer.start to restart the timer.

While I've found the 5 minute timer combined with motion sensor resets to be 99.99% reliable to avoid sudden lights out scenarios, there is still that 0.01% edge case. Therefore I intend to modify most of my automatic lighting setups to make use of a Home Assistant Counter integration. A counter will be defined for each set of automatic lights, and the motion sensor reset automation will also call counter.increment. Once the counter reaches a preset value representing the number of times shop motion has been detected, it will be assumed the shop is occupied and another automation will fire based upon the counter state that will call timer.cancel to stop the timer without generating a timer.finished event.

For now, if I (short) press the shop fab light button while the motion light timer is active, the timer is cancelled.

automations.yaml:

###########CANCEL ENTRY LIGHTS TIMER IF TIMER RUNNING
- id: 980432908320h98111
  alias: Shop Fab Light Button (Entry Timer Active)
  trigger:
  - platform: mqtt
    topic: /shop/s4/held/
  condition:
  - condition: numeric_state
    entity_id: sensor.shop_button_4
    above: 1
    below: 750  
  - condition: state
    entity_id: timer.shop_entry_lights
    state: 'active'  
  action:
  - data:
      entity_id: timer.shop_entry_lights
    service: timer.cancel

This automation need not turn on light.shop_fab_light as those lights are already on via the automatic entry lighting automation.

Hourly Chime

OK, this automation may be a little "fluffy" but I like it. As a child I remember spending time in the aunt's house, a big family house a few cities over. One of those memories is the large grandfather clock in the front hall, making its presence known every 15 minutes with an authoritative chime. 15 minutes is a little much so my chime plays every hour using a time_pattern to trigger when the current time is 1 minute past the hour. Why 1 minute? Because you can't supply "minutes: 0" in the trigger for some reason without generating a YAML parsing error. So 1 minute past the hour is damn close enough. As I type this, I guess triggering at "minutes: 59" and adding a "delay: 00:00:59" action before calling the media player would end up with a chime close enough to exactly on the hour as one could ever need. Another option would be a template trigger with some time parsing to output a "true" when the minutes evaluates to 00.

automations.yaml:

###########################HOURLY CHIME
- alias: Hourly Chime
  trigger:
  - platform: time_pattern
    minutes: 1
  condition:
  - condition: time
    after: '09:00:00'
    before: '23:00:00'
  - condition: template
    value_template: "{% if is_state('media_player.living_room_speaker', 'playing')\
      \ %}\n  false\n{% else %}\n  true\n{% endif %}\n"
  action:
  - service: media_player.play_media
    data_template:
      entity_id:
      - media_player.living_room_speaker
      - media_player.shop_speaker
      media_content_id: http://[HA IP]:8123/local/sounds/GrandFatherChime_strike.mp3
      media_content_type: audio/mp4
  id: a507e680563b4f2eaa7f99a9a8e4bbfa

The condition states that the automation is only allowed to fire between 9AM and 11PM as to not cause a disturbance during the night. Though I can't hear it from the bedroom, I don't want to hear it outside of "waking hours". A 2nd condition uses a template to evaluate "false" if the Google Home in the living room is playing, thus preventing the automation from firing if I am listening to something else. I'll sometimes request a daily news briefing (for a bit of depression to start the day) from the speaker and I don't want it interrupted.

Once the conditions are meant, the media_player.play_media service is called for the entities media_player.living_room_speaker and media_player.shop_speaker which represent two Googles Home Mini. The media itself is a short MP3 of a grandfather chime strike hosted via HA's built in web server to be accessible by the media players.

Router Reboot If No Ping ("Router Booter")

Doesn't matter how high quality your router is whether it be pro-sumer, small business or enterprise grade. At some point it will need to be rebooted to bring the Internet connection back up. Perhaps due to PPPoE going down and the router not being able to reconnect because the ISP limits reconnect attempts, or the ISP DHCP lease not renewing, or an ISP downstream issue. Regardless, we've all been there and done that. It is especially inconvenient if one isn't at home and suddenly finds access to services such as security cameras or Home Assistant unavailable due to lack of Internet connection. Thankfully, the solution is a simple "Router Booter" automation.

The Router Booter relies on ping sensors to detect whether or not the Internet connection is up. Every 60 seconds, the binary_sensor.isp_default_gateway_ping sends a ping to the first gateway after my router. This is typically the best way to determine whether a connection is up and how most pro-sumer/small business routers detect a WAN connection availability to determine fail over. I've also seen similar automations written by others that choose to ping publicly available DNS (such as Google's 8.8.8.8). The danger here is that if those public servers stop responding to pings, the automation could erroneously decide the Internet connection is down even though it is just a 3rd party server which isn't responding. There isn't much sense in using an address multiple hops away to determine the state of a local connection.

configuration.yaml:

binary_sensor:
########INTERNET CONNECTION PING SENSORS
  - platform: ping
    host: xxx.xxx.xxx.xxx
    name: "ISP DNS Ping"
    scan_interval: 60
  - platform: ping
    host: xxx.xxx.xxx.xxx
    name: "ISP Default Gateway Ping"
    scan_interval: 60

The 1st ping sensor, binary_sensor.isp_dns_ping is unrelated to this automation but something I keep track of for other reasons.

automations.yaml:


#######################IT AUTOMATIONS############################################
#######################################################################################
###########REBOOT ROUTER IF NO PING
- id: '9568133497643846847'
  alias: Reboot Router If No Ping To Gateway
  trigger:
  - entity_id: binary_sensor.isp_default_gateway_ping
    platform: state
    to: 'off'
    for:
      minutes: 10
  action:
  - data:
      topic: 'cmnd/routerbooter/POWER'
      payload: "OFF"
    service: mqtt.publish
  - delay: '00:00:30'
  - data:
      topic: 'cmnd/routerbooter/POWER'
      payload: "ON"
    service: mqtt.publish
  - delay: '00:05:00'
  - data:
      message: 'Internet was down for 10 minutes. Rebooted router 5 minutes ago.'
      title: 'HOUSE: Router Reboot'
    service: notify.aaron_email

The automation is fairly simple with one minor quirk. If the ping sensor (binary_sensor.isp_default_gateway) switches to "off" for 10 minutes, the Internet connection is down. The action of the automation is to call the mqtt.publish service to switch the Tasmota powered smart plug off via publishing cmnd/routerbooter/POWER = OFF . Plugged into that smart switch is the router. After a 30 second delay, cmnd/routerbooter/POWER = ON is published to turn the router back on. Now it can take several minutes for the router to renegotiate the connection (primarily due to long timeout values for authentication at my ISP, it only takes a few seconds for my router to boot) so there is a 5 minute delay before an email is sent to tell me that the router was just rebooted.

You're probably wondering why "routerbooter" isn't just a switch entity. I purposely didn't want that device represented in any way as an entity that could be accidentally toggled in the HA UI, via voice assistant, or any other way. So I choice to publish MQTT messages directly to the device instead. It keeps accidental fingers away from the switch. The smart plug is a Globe 50114 single outlet smart plug flashed with Tasmota. It is configured with a static IP address and the relay has been set to turn automatically on at power up via setting "PowerOnState 1" in the console. I know I have repeatedly voiced my distaste at using WiFi devices for permanent/fixed location devices so consider this a temporary setup until I buy or build a proper Ethernet connected PDU for my rack.

Turn Off Air Compressor If Not Home

This automation is stupid simple however is a perfect example of how home automation solves a real problem. I have a 5HP air compressor in a sound proof cabinet in my shop, plumbed into an air system which also extends into the house (What? You don't have a compressed air outlet in your kitchen or bathroom? Weird.). Therefore I end up turning the air compressor on from not only in the shop but also in the house via controls or by barking at a voice assistant or via an automation. Sometimes I forget to turn it off. I wouldn't want it to be powered up if I leave the house so solve this problem with an automation:

automations.yaml:

######AIR COMPRESSOR OFF WHEN LEAVE HOME
- id: '1048566243758563562484532323'
  alias: Air Compressor Off On Leave
  trigger:
  - entity_id: person.aaron
    from: 'home'
    platform: state
    #to: not_home
  condition:
  - condition: state
    entity_id: switch.air_compressor_switch
    state: 'on'
  action:
  - data:
      entity_id: switch.air_compressor_switch
    service: homeassistant.turn_off
  - data:
      message: 'You forgot to turn off the air compressor. Turning it off.'
      title: 'HOUSE: Turning Off Air Compressor'
    service: notify.aaron_email

And don't just turn it off, but send a condescending passive aggressive email reminding me I didn't turn it off.

Make Shop Heater More Effective - Turn On Vent Fan

The original purpose of this automation was actually to add a bit of safety in the shop for the few years I used a direct combustion forced air heater to keep the place toasty in the winter prior to installation of the natural gas heater. With the direct combustion heater, all the combustion products are blown into the area to be heated. And while that is mostly CO2 it is absolutely required that the area be ventilated to remove potentially harmful byproducts of incomplete combustion such as CO, soot (my fuel of choice is diesel) and other unpleasantness. Early on I found the thermostat on the heater to very much suck. Probably because it is too close to the floor and the hysteresis seemed to be about 6 degrees. So I just cranked the thermostat to maximum temp and instead controlled the heater via a generic thermostat which switched a Globe WiFi Smart Plug into which the heater was plugged. WiFi of course because the heater is only used half the year and otherwise put away. So this automation was created to run the shop vent fan automatically on low when the heater was operating. It made an enormous difference in shop air quality.

And then I installed the clean, quiet and most importantly outside vented natural gas unit heater. So I thought this automation wouldn't have any benefit except when I turned it off I immediately noticed that the fabrication area of the shop (room with workbenches, machines, tools) took a lot longer to warm up. Turns out that since the heater blows at a 90 degree angle to the fab area, airflow isn't encouraged into the dead-ended space. The intakes for the vent fan however are in the fab room. I found that running the fan on low created just enough draw to dramatically increase heating efficiency of the room.

There are three automations which make up this functionality. The first automation uses a template trigger to fire when the hvac_action attribute of the heater climate.shop_heating changes to "heating". As one might suspect, this indicates that the heater is actively heating. A condition checks to make sure the vent fan fan.shop_vent_fan is turned off. Because if the fan is already on for another reason at another speed, I don't want the automation to change the fan speed to low. Therefore, if the heater begins heating, and the vent fan is off, the fan is turned on at the low speed.

automations.yaml:

############VENT FAN ON LOW WHEN HEATER ON
 - alias: Shop Vent Fan On Low When Heater On
   trigger:
     platform: template
     value_template: "{{ is_state_attr('climate.shop_heating', 'hvac_action', 'heating') }}"
   condition:
   - condition: state
     entity_id: fan.shop_vent_fan
     state: 'off'
   action:
   #- delay: '00:00:20'
   - data:
       entity_id: fan.shop_vent_fan
       speed: low
     service: fan.set_speed
   id: '95888885555333322227'

The corresponding opposite automation turns the fan.shop_vent_fan off only if the speed is low ( {{ is_state_attr('fan.shop_vent_fan', 'speed', 'low') }} ), triggered by the attribute "hvac_action" changing, this time to "idle". The delay of 20 seconds before the fan is actually turned off is left over from using the this automation to vent combustion products from the previous heater and is no longer in use.

 #############SHOP VENT FAN OFF WHEN HEATER IDLE
 - alias: Shop Vent Fan Off When Heater Idle
   trigger:
     platform: template
     value_template: "{{ is_state_attr('climate.shop_heating', 'hvac_action', 'idle') }}"
   condition:
   - condition: template
     value_template: "{{ is_state_attr('fan.shop_vent_fan', 'speed', 'low') }}"
   - condition: state
     entity_id: fan.shop_vent_fan
     state: 'on'
   action:
#   - delay: '00:00:20'
   - data:
       entity_id: fan.shop_vent_fan
     service: homeassistant.turn_off
   id: '95886545676545756757756'

A final automation, which probably could simply be a condition of the above automation, turns the fan off when the state of climate.shop_heating changes to "off". This assures that if the shop heating is simply turned off, the fan is also switched off. Now there could be a scenario where I am in the shop, having set the fan to low speed, and then turn off the heater. This of course would have the unintended consequence of turning the fan off. This has also never happened.

 #############SHOP VENT FAN OFF WHEN HEATER TURNED OFF
 - alias: Shop Vent Fan Off When Heater Off
   trigger:
     platform: state
     entity_id: climate.shop_heating
     to: 'off'
   condition:
   - condition: template
     value_template: "{{ is_state_attr('fan.shop_vent_fan', 'speed', 'low') }}"
   - condition: state
     entity_id: fan.shop_vent_fan
     state: 'on'
   action:
   - data:
       entity_id: fan.shop_vent_fan
     service: homeassistant.turn_off
   id: '4532678420942985347864223498'

A grand total of 6 automations may not seem like much so it is important to remember that the system is in development. As new entities are added bringing online the ability to create more complex and useful automations, expect this list to significantly grow. I also don't see much point in listing all the mundane automations everyone makes use of as I'm not sure the world needs another example of setting a climate device mode to "away" when everyone leaves the house.

Navigation
<< Architecture and Application

Home Automation
Home Assistant
Hosting Hardware
Protocols And Standards
I/O Control
DIY Power Bars and Outlets
Commercial Power Bars and Outlets
Sensors
HVAC
Voice Control
Architecture and Application
Automations
Lessons Learned
Lessons Learned >>

Back To Home Automation Page | Mail Me | Search