Fully automated luxury home climate with Home Assistant

published Aug 16, 2023

If you live in a Home Assistant smart home, there's no need to remember to turn off the A/C or the heating, like a caveman.

Fully automated luxury home climate with Home Assistant

If you're anything like me, you might have a lot on your mind... which leads you to forget doing trivial things.  Like turning off the air conditioner when you leave home, or you open a window.

Do not despair.  Here is a sample Home Assistant automation that does it all for you, complete with code.

Thanks to this setup (and the prior high-precision thermostat work) we no longer need to do anything with the A/C.  When it needs to run, it runs.  When it doesn't need to, it's off.  And when it's running, the temperature is just perfect for us.

Of course, you can modify the automation as you see fit — perhaps you'd like your heaters to turn off when you leave... and you can do that too.

This is how my dashboard looks like when the automation has kicked in.  I will soon share how this dashboard is set up:

Requisites

This automation depends on the following:

  • A climate entity.  In the sample below, it's called climate.living_space.
    • Note that you can modify the automation to govern your home heating climate entities as well.
  • An input boolean that lets you suspend the A/C unit.  In the sample below, it's called input_boolean.air_conditioning_suspended.
  • Some sensors for certain states at home, which will be inputs for the automation.  In the sample below, they are:
    • binary_sensor.indoors_windows
      • Flips to on after we open a window or a door that lets outside air in.
      • Flips to off immediately after all windows and doors communicating with the outside are closed
      • In my case, the sensor is a tad more complex since it takes into account things like, Is the bedroom door closed?  then it doesn't matter if the windows of the bedroom are open.
      • Use whatever makes sense for your home.
    • binary_sensor.natural_ventilation_active
      • It's pretty much the same as the previous sensor, but with the following caveat: in this sensor, entranceway doors only cause the sensor to flip to on after thirty seconds.
      • The purpose of this sensor is to allow the air conditioner to run for a little longer than 5 seconds — well, half a minute — after a door has been opened.  This gives us a bit of time between the A/C detecting us at home, and us walking in with the entranceway door open.
    • binary_sensor.no_ventilation_for_air_conditioner_compressor
      • Flips to on if the windows where the compressor part of the air conditioner are closed.  It's a safety mechanism to prevent that room from getting to 50 degrees Celsius.
    • binary_sensor.someone_home
      • Flips to off when no one is home, and on back when someone is detected at home.
    • input_boolean.vacation_mode
      • This one is the simplest — we enable it when we go on vacation, and we turn it off (or, rather, an automation turns it off) when we return home.

What does the automation do?

The tasks the automation makes itself responsible for are very straightforward:

  1. If any one of these sensor conditions flips to true1, then (depending on the condition, maybe after a few seconds, or maybe immediately) the input_boolean.air_conditioning_suspended is flipped to true.
  2. If all of these sensor conditions flip to false1, then the input_boolean.air_conditioning_suspended is flipped to false.
  3. Whenever the input_boolean.air_conditioning_suspended boolean is flipped to true, the air conditioner is commanded to turn off.
  4. Whenever the input_boolean.air_conditioning_suspended boolean is flipped to false, the air conditioner is commanded to turn on.
  5. If the air conditioner is turned on manually, the boolean is flipped to false — because, obviously, the user's intention was to run the unit anyway.

Code

alias: "A/C: suspend or restore as needed"
description: ""
trigger:
- platform: state
entity_id:
- binary_sensor.natural_ventilation_active
to: "on"
for:
hours: 0
minutes: 0
seconds: 30
id: outdoor_access_open
- platform: state
entity_id:
- binary_sensor.indoors_windows
to: "on"
for:
hours: 0
minutes: 0
seconds: 5
id: windows_open
- platform: state
entity_id:
- binary_sensor.no_ventilation_for_air_conditioner_compressor
from: "on"
to: "off"
id: ventilation_on
- platform: template
value_template: >-
{{ not (is_state("input_boolean.vacation_mode", "off") and
is_state("binary_sensor.someone_home", "on")) }}
id: away_or_vacay
alias: No one home or vacay
- platform: state
entity_id:
- binary_sensor.natural_ventilation_active
for:
hours: 0
minutes: 0
seconds: 5
to: "off"
id: outdoor_access_closed
- platform: state
entity_id:
- binary_sensor.indoors_windows
to: "off"
for:
hours: 0
minutes: 0
seconds: 5
id: windows_closed
- platform: state
entity_id:
- binary_sensor.no_ventilation_for_air_conditioner_compressor
from: "off"
to: "on"
id: ventilation_off
- platform: template
value_template: >-
{{ is_state("input_boolean.vacation_mode", "off") and
is_state("binary_sensor.someone_home", "on") }}
id: someone_home
alias: Someone home without vacay
- platform: state
entity_id:
- input_boolean.air_conditioning_suspended
from: "off"
to: "on"
alias: suspended
id: suspended
- platform: state
entity_id:
- input_boolean.air_conditioning_suspended
from: "on"
to: "off"
alias: unsuspended
id: unsuspended
- platform: state
entity_id:
- climate.living_space
from: "off"
to: cool
id: turned_on
condition:
- condition: template
value_template: "{{ has_value(\"climate.living_space\") }}"
alias: A/C controller is available
action:
- choose:
- conditions:
- condition: or
conditions:
- condition: trigger
id:
- outdoor_access_open
- away_or_vacay
- condition: and
conditions:
- condition: trigger
id:
- windows_open
- condition: state
entity_id: binary_sensor.natural_ventilation_active
state: "on"
alias: Windows open with outside air access
- condition: trigger
id:
- ventilation_off
alias: Compressor ventilation off
- condition: template
value_template: >-
{{ is_state("climate.living_space", "cool") or
is_state("climate.living_space", "dry") or
is_state("climate.living_space", "fan_only") }}
alias: A/C on
- condition: state
entity_id: input_boolean.air_conditioning_suspended
state: "off"
sequence:
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.air_conditioning_suspended
- conditions:
- condition: and
conditions:
- condition: trigger
id:
- outdoor_access_closed
- windows_closed
- ventilation_on
- someone_home
alias: >-
Windows or outside access closed or return to home or ventilation
for A/C restored
- condition: state
entity_id: binary_sensor.no_ventilation_for_air_conditioner_compressor
state: "off"
- condition: state
entity_id: binary_sensor.natural_ventilation_active
state: "off"
- condition: state
entity_id: binary_sensor.indoors_windows
state: "off"
- condition: state
entity_id: binary_sensor.someone_home
state: "on"
- condition: state
entity_id: input_boolean.air_conditioning_suspended
state: "on"
sequence:
- service: input_boolean.turn_off
data: {}
target:
entity_id: input_boolean.air_conditioning_suspended
enabled: true
- conditions:
- condition: trigger
id:
- turned_on
- condition: state
entity_id: input_boolean.air_conditioning_suspended
state: "on"
sequence:
- service: input_boolean.turn_off
data: {}
target:
entity_id: input_boolean.air_conditioning_suspended
- conditions:
- condition: trigger
id:
- suspended
- condition: state
entity_id: climate.living_space
state: cool
sequence:
- service: climate.turn_off
data: {}
target:
entity_id:
- climate.living_space
- wait_for_trigger:
- platform: state
entity_id:
- climate.living_space
to: "off"
for:
hours: 0
minutes: 0
seconds: 0
timeout:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
alias: Wait for living space to change to off
- conditions:
- condition: trigger
id:
- unsuspended
- condition: state
entity_id: climate.living_space
state: "off"
sequence:
- service: climate.turn_on
data: {}
target:
entity_id:
- climate.living_space
enabled: true
- wait_for_trigger:
- platform: state
entity_id:
- climate.living_space
to: cool
for:
hours: 0
minutes: 0
seconds: 0
timeout:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
alias: Wait for living space to change to cool
mode: queued
max: 10