|
|
######################################################################
|
|
|
# @CCOSTAN - Follow Me on X
|
|
|
# For more info visit https://www.vcloudinfo.com/click-here
|
|
|
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
|
|
|
# -------------------------------------------------------------------
|
|
|
# Climate Control - Seasonal HVAC automations and sensors.
|
|
|
# Thermostat helpers for upstairs/downstairs comfort.
|
|
|
# -------------------------------------------------------------------
|
|
|
# Related Issue: 1571, 273
|
|
|
# Notes: Filter due alerts use a 350h runtime threshold, 9-month hard limit, 3-day snooze, and Filter Changed push actions.
|
|
|
# Notes: Condenser line cleanout uses a single 360-day reminder for both HVAC systems.
|
|
|
# Notes: The snooze notification pattern is also covered at https://youtu.be/y47KSflS1aw.
|
|
|
# Video: https://youtu.be/nScl2JxYSB8
|
|
|
######################################################################
|
|
|
# Contact: @CCOSTAN | Entity reference details below
|
|
|
# Entity reference and attribute summaries:
|
|
|
#
|
|
|
# Entity ID: climate.downstairs
|
|
|
# Supported hvac_modes: heat, cool, heat_cool, off
|
|
|
# Supported fan_modes: on, off
|
|
|
# Supported preset_modes: none, eco
|
|
|
# Supported temperature range: 50°F (min_temp) – 90°F (max_temp)
|
|
|
#
|
|
|
# Current state (example):
|
|
|
# current_temperature: 77
|
|
|
# temperature: 83
|
|
|
# target_temp_high: null
|
|
|
# target_temp_low: null
|
|
|
# current_humidity: 58
|
|
|
# fan_mode: off
|
|
|
# hvac_action: idle
|
|
|
# preset_mode: none
|
|
|
# Supported features: 411
|
|
|
# --------------------------------------------------------------
|
|
|
# Entity ID: climate.upstairs
|
|
|
# Supported hvac_modes: off, heat, cool, heat_cool
|
|
|
# Supported temperature range: 50°F (min_temp) – 90°F (max_temp)
|
|
|
#
|
|
|
# Current state (example):
|
|
|
# current_temperature: 76
|
|
|
# temperature: 78
|
|
|
# target_temp_high: null
|
|
|
# target_temp_low: null
|
|
|
# friendly_name: Upstairs
|
|
|
# Supported features: 387
|
|
|
|
|
|
######################################################################
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# Template helpers – compressor status flags and numeric runtime helpers
|
|
|
# ---------------------------------------------------------------------------
|
|
|
template:
|
|
|
- binary_sensor:
|
|
|
- name: "Downstairs AC is Cooling"
|
|
|
unique_id: downstairs_ac_cooling
|
|
|
state: >
|
|
|
{% set action = state_attr('climate.downstairs', 'hvac_action') %}
|
|
|
{% set current = state_attr('climate.downstairs', 'current_temperature') | float(none) %}
|
|
|
{% set target = state_attr('climate.downstairs', 'temperature') | float(none) %}
|
|
|
{{
|
|
|
action == 'cooling'
|
|
|
or (
|
|
|
action is none
|
|
|
and is_state('climate.downstairs', 'cool')
|
|
|
and current is not none
|
|
|
and target is not none
|
|
|
and current > target
|
|
|
)
|
|
|
}}
|
|
|
- name: "Upstairs AC is Cooling"
|
|
|
unique_id: upstairs_ac_cooling
|
|
|
state: >
|
|
|
{% set action = state_attr('climate.upstairs', 'hvac_action') %}
|
|
|
{% set current = state_attr('climate.upstairs', 'current_temperature') | float(none) %}
|
|
|
{% set target = state_attr('climate.upstairs', 'temperature') | float(none) %}
|
|
|
{{
|
|
|
action == 'cooling'
|
|
|
or (
|
|
|
action is none
|
|
|
and is_state('climate.upstairs', 'cool')
|
|
|
and current is not none
|
|
|
and target is not none
|
|
|
and current > target
|
|
|
)
|
|
|
}}
|
|
|
|
|
|
sensor:
|
|
|
- name: "Downstairs AC Cooling Numeric"
|
|
|
unique_id: downstairs_ac_cooling_numeric
|
|
|
state: "{{ 1 if is_state('binary_sensor.downstairs_ac_is_cooling', 'on') else 0 }}"
|
|
|
- name: "Upstairs AC Cooling Numeric"
|
|
|
unique_id: upstairs_ac_cooling_numeric
|
|
|
state: "{{ 1 if is_state('binary_sensor.upstairs_ac_is_cooling', 'on') else 0 }}"
|
|
|
|
|
|
input_datetime:
|
|
|
downstairs_last_filter_change:
|
|
|
name: Downstairs Last Filter Change
|
|
|
has_date: true
|
|
|
has_time: true
|
|
|
downstairs_filter_snooze_until:
|
|
|
name: Downstairs Filter Snooze Until
|
|
|
has_date: true
|
|
|
has_time: true
|
|
|
upstairs_last_filter_change:
|
|
|
name: Upstairs Last Filter Change
|
|
|
has_date: true
|
|
|
has_time: true
|
|
|
upstairs_filter_snooze_until:
|
|
|
name: Upstairs Filter Snooze Until
|
|
|
has_date: true
|
|
|
has_time: true
|
|
|
hvac_condenser_lines_last_cleaned:
|
|
|
name: HVAC Condenser Lines Last Cleaned
|
|
|
has_date: true
|
|
|
has_time: false
|
|
|
initial: "2026-06-28"
|
|
|
hvac_condenser_lines_cleaning_snooze_until:
|
|
|
name: HVAC Condenser Lines Cleaning Snooze Until
|
|
|
has_date: true
|
|
|
has_time: true
|
|
|
initial: "2026-06-28 00:00:00"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# Integration sensors tally runtime based on compressor state
|
|
|
# ---------------------------------------------------------------------------
|
|
|
sensor:
|
|
|
- platform: integration
|
|
|
name: Downstairs AC Runtime Raw
|
|
|
source: sensor.downstairs_ac_cooling_numeric
|
|
|
unit_time: h
|
|
|
method: left
|
|
|
round: 2
|
|
|
- platform: integration
|
|
|
name: Upstairs AC Runtime Raw
|
|
|
source: sensor.upstairs_ac_cooling_numeric
|
|
|
unit_time: h
|
|
|
method: left
|
|
|
round: 2
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# Utility‑meters that act like odometers (reset when you swap the filter)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
utility_meter:
|
|
|
downstairs_ac_runtime_since_last_filter_change:
|
|
|
source: sensor.downstairs_ac_runtime_raw
|
|
|
upstairs_ac_runtime_since_last_filter_change:
|
|
|
source: sensor.upstairs_ac_runtime_raw
|
|
|
|
|
|
script:
|
|
|
reset_downstairs_filter:
|
|
|
alias: Reset Downstairs Filter
|
|
|
mode: queued
|
|
|
sequence:
|
|
|
- service: input_datetime.set_datetime
|
|
|
data:
|
|
|
entity_id: input_datetime.downstairs_last_filter_change
|
|
|
datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
- service: input_datetime.set_datetime
|
|
|
data:
|
|
|
entity_id: input_datetime.downstairs_filter_snooze_until
|
|
|
datetime: "{{ (now() - timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
- service: utility_meter.reset
|
|
|
target:
|
|
|
entity_id: sensor.downstairs_ac_runtime_since_last_filter_change
|
|
|
|
|
|
reset_upstairs_filter:
|
|
|
alias: Reset Upstairs Filter
|
|
|
mode: queued
|
|
|
sequence:
|
|
|
- service: input_datetime.set_datetime
|
|
|
data:
|
|
|
entity_id: input_datetime.upstairs_last_filter_change
|
|
|
datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
- service: input_datetime.set_datetime
|
|
|
data:
|
|
|
entity_id: input_datetime.upstairs_filter_snooze_until
|
|
|
datetime: "{{ (now() - timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
- service: utility_meter.reset
|
|
|
target:
|
|
|
entity_id: sensor.upstairs_ac_runtime_since_last_filter_change
|
|
|
|
|
|
reset_hvac_condenser_lines_cleaned:
|
|
|
alias: Reset HVAC Condenser Lines Cleaned
|
|
|
mode: queued
|
|
|
sequence:
|
|
|
- service: input_datetime.set_datetime
|
|
|
data:
|
|
|
entity_id: input_datetime.hvac_condenser_lines_last_cleaned
|
|
|
date: "{{ now().strftime('%Y-%m-%d') }}"
|
|
|
- service: input_datetime.set_datetime
|
|
|
data:
|
|
|
entity_id: input_datetime.hvac_condenser_lines_cleaning_snooze_until
|
|
|
datetime: "{{ (now() - timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
|
|
|
set_downstairs_target_temp_based_on_conditions:
|
|
|
alias: Set Downstairs Target Temperature Based on Conditions
|
|
|
mode: single
|
|
|
sequence:
|
|
|
- choose:
|
|
|
- conditions:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'not_home'
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Downstairs HVAC set to ECO (family not_home)."
|
|
|
- service: climate.set_preset_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
preset_mode: 'eco'
|
|
|
- conditions:
|
|
|
- condition: and
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'home'
|
|
|
- condition: template
|
|
|
value_template: >-
|
|
|
{{ states('sensor.pirateweather_temperature') in ['unknown','unavailable','none',''] }}
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Outside temp unavailable; allowing downstairs cool mode (defaulting to 80F)."
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
hvac_mode: cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 80
|
|
|
|
|
|
- conditions:
|
|
|
- condition: and
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'home'
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
below: 78
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Downstairs target set to 78F (family home, outside temp <78F)."
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
hvac_mode: cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 78
|
|
|
- conditions:
|
|
|
- condition: and
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'home'
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
above: 92
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Downstairs target set to 78F (family home, temp >92F)."
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
hvac_mode: cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 78
|
|
|
- conditions:
|
|
|
- condition: and
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'home'
|
|
|
- condition: template
|
|
|
value_template: "{{ states('sensor.pirateweather_temperature')|float(-999) >= 78 }}"
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Downstairs target set to 80F (family home)."
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
hvac_mode: cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 80
|
|
|
|
|
|
set_downstairs_daytime_target:
|
|
|
alias: Set Downstairs Daytime Target
|
|
|
mode: single
|
|
|
sequence:
|
|
|
- service: script.set_downstairs_target_temp_based_on_conditions
|
|
|
|
|
|
set_downstairs_hvac_cool:
|
|
|
alias: Set Downstairs HVAC Cool
|
|
|
mode: single
|
|
|
sequence:
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
hvac_mode: cool
|
|
|
|
|
|
set_upstairs_cool_82:
|
|
|
alias: Set Upstairs Cool 82
|
|
|
mode: single
|
|
|
sequence:
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.upstairs
|
|
|
hvac_mode: cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.upstairs
|
|
|
temperature: 82
|
|
|
|
|
|
##############################################################################
|
|
|
### AUTOMATIONS - Thermostat schedules, guardrails, and presence/weather logic
|
|
|
### Some shutoff automations are also in the ALARM.yaml package when windows/doors are left open.
|
|
|
### There are also some automations in the POWERWALL.yaml package when the grid is down.
|
|
|
##############################################################################
|
|
|
automation:
|
|
|
- alias: Notify Climate Filter Change Due
|
|
|
description: Notify when HVAC filter runtime exceeds 350h or age reaches 9 months
|
|
|
trigger:
|
|
|
- platform: numeric_state
|
|
|
entity_id: sensor.downstairs_ac_runtime_since_last_filter_change
|
|
|
above: 350
|
|
|
id: downstairs_runtime
|
|
|
- platform: time
|
|
|
at: "09:00:00"
|
|
|
id: downstairs_daily
|
|
|
- platform: numeric_state
|
|
|
entity_id: sensor.upstairs_ac_runtime_since_last_filter_change
|
|
|
above: 350
|
|
|
id: upstairs_runtime
|
|
|
- platform: time
|
|
|
at: "09:10:00"
|
|
|
id: upstairs_daily
|
|
|
variables:
|
|
|
location: "{{ 'upstairs' if trigger.id.startswith('upstairs') else 'downstairs' }}"
|
|
|
location_title: "{{ 'Upstairs' if location == 'upstairs' else 'Downstairs' }}"
|
|
|
runtime_sensor: "sensor.{{ location }}_ac_runtime_since_last_filter_change"
|
|
|
last_filter_entity: "input_datetime.{{ location }}_last_filter_change"
|
|
|
snooze_entity: "input_datetime.{{ location }}_filter_snooze_until"
|
|
|
runtime_hours: "{{ states(runtime_sensor) | float(0) }}"
|
|
|
last_filter_ts: "{{ as_timestamp(states(last_filter_entity), 0) }}"
|
|
|
filter_age_days: "{{ ((as_timestamp(now()) - (last_filter_ts | float(0))) / 86400) | round(0) }}"
|
|
|
due_reason: >-
|
|
|
{% set runtime_due = runtime_hours | float(0) > 350 %}
|
|
|
{% set age_due = (last_filter_ts | float(0)) == 0 or (filter_age_days | int(0)) >= 274 %}
|
|
|
{% if runtime_due and age_due %}
|
|
|
Runtime has exceeded 350h and the filter is {{ filter_age_days }} days old.
|
|
|
{% elif runtime_due %}
|
|
|
Runtime has exceeded 350h.
|
|
|
{% else %}
|
|
|
Filter age has reached the 9-month hard limit ({{ filter_age_days }} days).
|
|
|
{% endif %}
|
|
|
condition:
|
|
|
- condition: template
|
|
|
value_template: >-
|
|
|
{{
|
|
|
(runtime_hours | float(0) > 350)
|
|
|
or (last_filter_ts | float(0)) == 0
|
|
|
or (filter_age_days | int(0)) >= 274
|
|
|
}}
|
|
|
- condition: template
|
|
|
value_template: >-
|
|
|
{% set snooze_until = as_timestamp(states(snooze_entity), 0) %}
|
|
|
{{ snooze_until <= as_timestamp(now()) }}
|
|
|
action:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "MAINTENANCE"
|
|
|
message: >-
|
|
|
{{ location_title }} AC filter due. {{ due_reason }} Runtime is {{ runtime_hours | round(1) }}h.
|
|
|
- service: script.notify_engine_two_button
|
|
|
data:
|
|
|
title: "Home Maintenance Reminder"
|
|
|
value1: "It's time to change your {{ location_title }} AC filter."
|
|
|
value2: >
|
|
|
{{ due_reason }} Runtime is {{ runtime_hours | round(1) }}h.
|
|
|
title1: "Snooze 3d"
|
|
|
action1: "{{ 'SNOOZE_UPSTAIRS_FILTER_3D' if location == 'upstairs' else 'SNOOZE_DOWNSTAIRS_FILTER_3D' }}"
|
|
|
icon1: "sfsymbols:clock"
|
|
|
title2: "Filter Changed"
|
|
|
action2: "{{ 'RESET_UPSTAIRS_FILTER' if location == 'upstairs' else 'RESET_DOWNSTAIRS_FILTER' }}"
|
|
|
icon2: "sfsymbols:checkmark.circle"
|
|
|
who: "carlo"
|
|
|
group: "maintenance"
|
|
|
level: "active"
|
|
|
|
|
|
- alias: Climate Filter Reminder Actions
|
|
|
id: 6d7056d0-90ce-4c4f-b8b1-fd32a7e58311
|
|
|
mode: queued
|
|
|
trigger:
|
|
|
- platform: event
|
|
|
event_type: mobile_app_notification_action
|
|
|
event_data:
|
|
|
action: SNOOZE_DOWNSTAIRS_FILTER_3D
|
|
|
id: downstairs_snooze
|
|
|
- platform: event
|
|
|
event_type: mobile_app_notification_action
|
|
|
event_data:
|
|
|
action: SNOOZE_UPSTAIRS_FILTER_3D
|
|
|
id: upstairs_snooze
|
|
|
- platform: event
|
|
|
event_type: mobile_app_notification_action
|
|
|
event_data:
|
|
|
action: RESET_DOWNSTAIRS_FILTER
|
|
|
id: downstairs_reset
|
|
|
- platform: event
|
|
|
event_type: mobile_app_notification_action
|
|
|
event_data:
|
|
|
action: RESET_UPSTAIRS_FILTER
|
|
|
id: upstairs_reset
|
|
|
variables:
|
|
|
location: "{{ 'upstairs' if trigger.id.startswith('upstairs') else 'downstairs' }}"
|
|
|
location_title: "{{ 'Upstairs' if location == 'upstairs' else 'Downstairs' }}"
|
|
|
snooze_entity: "input_datetime.{{ location }}_filter_snooze_until"
|
|
|
reset_script: "script.reset_{{ location }}_filter"
|
|
|
action:
|
|
|
- choose:
|
|
|
- conditions: "{{ trigger.id.endswith('_snooze') }}"
|
|
|
sequence:
|
|
|
- variables:
|
|
|
snooze_until: "{{ (now() + timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
- service: input_datetime.set_datetime
|
|
|
target:
|
|
|
entity_id: "{{ snooze_entity }}"
|
|
|
data:
|
|
|
datetime: "{{ snooze_until }}"
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "MAINTENANCE"
|
|
|
message: "{{ location_title }} AC filter reminder snoozed until {{ snooze_until }}."
|
|
|
- conditions: "{{ trigger.id.endswith('_reset') }}"
|
|
|
sequence:
|
|
|
- service: "{{ reset_script }}"
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "MAINTENANCE"
|
|
|
message: "{{ location_title }} AC filter reset from notification action."
|
|
|
|
|
|
- alias: Notify HVAC Condenser Lines Cleaning Due
|
|
|
id: 4dafac96-3163-4d63-847a-76727005f75b
|
|
|
description: Notify every 360 days when the outdoor condenser lines should be cleaned
|
|
|
trigger:
|
|
|
- platform: time
|
|
|
at: "09:20:00"
|
|
|
variables:
|
|
|
cleaned: "{{ states('input_datetime.hvac_condenser_lines_last_cleaned') }}"
|
|
|
cleaned_ts: >-
|
|
|
{% if cleaned in ['unknown', 'unavailable', 'none', ''] %}
|
|
|
0
|
|
|
{% else %}
|
|
|
{{ as_timestamp(strptime(cleaned, '%Y-%m-%d'), 0) }}
|
|
|
{% endif %}
|
|
|
days_since_cleaned: "{{ ((as_timestamp(now()) - (cleaned_ts | float(0))) / 86400) | round(0) }}"
|
|
|
condition:
|
|
|
- condition: template
|
|
|
value_template: "{{ (cleaned_ts | float(0)) == 0 or (days_since_cleaned | int(0)) >= 360 }}"
|
|
|
- condition: template
|
|
|
value_template: >-
|
|
|
{% set snooze_until = as_timestamp(states('input_datetime.hvac_condenser_lines_cleaning_snooze_until'), 0) %}
|
|
|
{{ snooze_until <= as_timestamp(now()) }}
|
|
|
action:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "MAINTENANCE"
|
|
|
message: "HVAC condenser lines cleanout due; last cleaned {{ days_since_cleaned }} days ago."
|
|
|
- service: script.notify_engine_two_button
|
|
|
data:
|
|
|
title: "Home Maintenance Reminder"
|
|
|
value1: "Clean the HVAC condenser lines."
|
|
|
value2: "360-day cleanout is due; last cleaned {{ days_since_cleaned }} days ago."
|
|
|
title1: "Snooze 3d"
|
|
|
action1: "SNOOZE_HVAC_CONDENSER_LINES_3D"
|
|
|
icon1: "sfsymbols:clock"
|
|
|
title2: "Cleaned"
|
|
|
action2: "RESET_HVAC_CONDENSER_LINES_CLEANED"
|
|
|
icon2: "sfsymbols:checkmark.circle"
|
|
|
who: "carlo"
|
|
|
group: "maintenance"
|
|
|
level: "active"
|
|
|
|
|
|
- alias: Climate Condenser Lines Reminder Actions
|
|
|
id: dfe89869-4bd3-47f6-bf0d-612bf7ee949f
|
|
|
mode: queued
|
|
|
trigger:
|
|
|
- platform: event
|
|
|
event_type: mobile_app_notification_action
|
|
|
event_data:
|
|
|
action: SNOOZE_HVAC_CONDENSER_LINES_3D
|
|
|
id: snooze
|
|
|
- platform: event
|
|
|
event_type: mobile_app_notification_action
|
|
|
event_data:
|
|
|
action: RESET_HVAC_CONDENSER_LINES_CLEANED
|
|
|
id: reset
|
|
|
action:
|
|
|
- choose:
|
|
|
- conditions: "{{ trigger.id == 'snooze' }}"
|
|
|
sequence:
|
|
|
- variables:
|
|
|
snooze_until: "{{ (now() + timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') }}"
|
|
|
- service: input_datetime.set_datetime
|
|
|
target:
|
|
|
entity_id: input_datetime.hvac_condenser_lines_cleaning_snooze_until
|
|
|
data:
|
|
|
datetime: "{{ snooze_until }}"
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "MAINTENANCE"
|
|
|
message: "HVAC condenser lines cleanout reminder snoozed until {{ snooze_until }}."
|
|
|
- conditions: "{{ trigger.id == 'reset' }}"
|
|
|
sequence:
|
|
|
- service: script.reset_hvac_condenser_lines_cleaned
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "MAINTENANCE"
|
|
|
message: "HVAC condenser lines cleanout reset from notification action."
|
|
|
|
|
|
- alias: 'AC Status Announcement'
|
|
|
id: 7812fdaf-a3f8-498b-8f07-28e977e528fe
|
|
|
trigger:
|
|
|
- platform: state
|
|
|
entity_id:
|
|
|
- climate.downstairs
|
|
|
- climate.upstairs
|
|
|
from: 'off'
|
|
|
- platform: state
|
|
|
entity_id:
|
|
|
- climate.downstairs
|
|
|
- climate.upstairs
|
|
|
to: 'off'
|
|
|
action:
|
|
|
- service: script.speech_engine
|
|
|
data:
|
|
|
NestStatus: "The {{ trigger.entity_id.split('.')[1].split('_')[0]}} {{ trigger.entity_id.split('.')[1].split('_')[1]}} has now been turned on for {{(trigger.to_state.state)}}."
|
|
|
call_window_check: 1
|
|
|
|
|
|
- alias: Prevent Upstairs Nest Below 76
|
|
|
id: 7812fdaf-a3f8-498b-8f07-28e977e528ff
|
|
|
trigger:
|
|
|
- platform: numeric_state
|
|
|
entity_id: climate.upstairs
|
|
|
attribute: temperature
|
|
|
below: 76
|
|
|
condition:
|
|
|
- condition: template
|
|
|
value_template: "{{ is_state('binary_sensor.powerwall_grid_status', 'on') }}"
|
|
|
action:
|
|
|
- delay: "00:03:00"
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.upstairs
|
|
|
temperature: 78
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Upstairs target temp corrected to 78F (guardrail)."
|
|
|
|
|
|
- alias: Set Downstairs Bedtime Target When Both in Bed
|
|
|
id: set_downstairs_nest_77_both_in_bed
|
|
|
trigger:
|
|
|
- platform: state
|
|
|
entity_id: group.bed
|
|
|
to: 'on'
|
|
|
condition:
|
|
|
- condition: and
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: binary_sensor.sleepnumber_carlo_carlo_is_in_bed
|
|
|
state: 'on'
|
|
|
- condition: state
|
|
|
entity_id: binary_sensor.sleepnumber_carlo_stacey_is_in_bed
|
|
|
state: 'on'
|
|
|
- condition: state
|
|
|
entity_id: binary_sensor.powerwall_grid_status
|
|
|
state: 'on'
|
|
|
- condition: state
|
|
|
entity_id: sun.sun
|
|
|
state: 'below_horizon'
|
|
|
action:
|
|
|
- choose:
|
|
|
- conditions:
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
above: 80
|
|
|
sequence:
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 77
|
|
|
- conditions:
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
above: 75
|
|
|
below: 80
|
|
|
sequence:
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 79
|
|
|
|
|
|
- alias: 'Set Downstairs Thermostat Daytime Target'
|
|
|
id: set_downstairs_thermostat_daytime_target
|
|
|
mode: single
|
|
|
trigger:
|
|
|
- platform: state
|
|
|
entity_id: sun.sun
|
|
|
to: 'above_horizon'
|
|
|
- platform: time
|
|
|
at: "08:00:00"
|
|
|
- platform: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
above: 92
|
|
|
condition:
|
|
|
- condition: and
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: sun.sun
|
|
|
state: 'above_horizon'
|
|
|
- condition: state
|
|
|
entity_id: input_boolean.guest_mode
|
|
|
state: 'off'
|
|
|
- condition: state
|
|
|
entity_id: binary_sensor.powerwall_grid_status
|
|
|
state: 'on'
|
|
|
action:
|
|
|
- service: script.set_downstairs_daytime_target
|
|
|
|
|
|
# Set thermostats to eco mode when everyone is away
|
|
|
- alias: 'Set Thermostats to Eco When Away'
|
|
|
id: 1e2d3c4b-eco-thermostat-away
|
|
|
mode: single
|
|
|
trigger:
|
|
|
- platform: state
|
|
|
entity_id: group.family
|
|
|
to: 'not_home'
|
|
|
condition:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'not_home'
|
|
|
- condition: state
|
|
|
entity_id: input_boolean.guest_mode
|
|
|
state: 'off'
|
|
|
action:
|
|
|
- service: climate.set_preset_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
preset_mode: 'eco'
|
|
|
- choose:
|
|
|
- conditions:
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
below: 75
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Skipping downstairs cool mode (outside temp <75F)."
|
|
|
default:
|
|
|
- service: script.set_downstairs_hvac_cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.upstairs
|
|
|
temperature: 83
|
|
|
|
|
|
# Automation: Set Thermostats Back to Cool Mode
|
|
|
- alias: 'Set Thermostats to Cool When Home'
|
|
|
id: 1e2d3c4b-cool-thermostat-home
|
|
|
mode: single
|
|
|
trigger:
|
|
|
- platform: state
|
|
|
entity_id: group.family
|
|
|
to: 'home'
|
|
|
condition:
|
|
|
- condition: or
|
|
|
conditions:
|
|
|
- condition: state
|
|
|
entity_id: group.family
|
|
|
state: 'home'
|
|
|
- condition: template
|
|
|
value_template: "{{ is_state('input_boolean.guest_mode', 'off') }}"
|
|
|
- condition: state
|
|
|
entity_id: binary_sensor.powerwall_grid_status
|
|
|
state: 'on'
|
|
|
action:
|
|
|
- service: climate.set_preset_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
preset_mode: 'none'
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.upstairs
|
|
|
hvac_mode: cool
|
|
|
- service: script.set_downstairs_target_temp_based_on_conditions
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.upstairs
|
|
|
temperature: 82
|
|
|
|
|
|
- alias: 'Reset Upstairs to 82 Each Night'
|
|
|
id: reset_upstairs_thermostat_nightly_82
|
|
|
mode: single
|
|
|
trigger:
|
|
|
- platform: time
|
|
|
at: "03:00:00"
|
|
|
condition:
|
|
|
- condition: template
|
|
|
value_template: "{{ states('binary_sensor.powerwall_grid_status') == 'on' }}"
|
|
|
action:
|
|
|
- service: script.set_upstairs_cool_82
|
|
|
|
|
|
- alias: 'Humidity Control'
|
|
|
id: AC_Humidity_Control
|
|
|
mode: single
|
|
|
trigger:
|
|
|
- platform: numeric_state
|
|
|
entity_id: sensor.downstairs_humidity
|
|
|
above: 60
|
|
|
- platform: time
|
|
|
at: "02:00:00"
|
|
|
condition:
|
|
|
- condition: time
|
|
|
after: "01:00:00"
|
|
|
before: "08:00:00"
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.downstairs_humidity
|
|
|
above: 60
|
|
|
- condition: template #Only needed in the winter months
|
|
|
value_template: "{{ now().month in [10, 11, 12, 1, 2, 3] }}"
|
|
|
- condition: template # Only run if AC is idle (prevents fighting other automations)
|
|
|
value_template: "{{ state_attr('climate.downstairs', 'hvac_action') == 'idle' }}"
|
|
|
- condition: template # Never run if the grid is down and running on powerwall.
|
|
|
value_template: "{{ states('binary_sensor.powerwall_grid_status')|lower == 'on' }}"
|
|
|
action:
|
|
|
- choose:
|
|
|
- conditions:
|
|
|
- condition: numeric_state
|
|
|
entity_id: sensor.pirateweather_temperature
|
|
|
below: 75
|
|
|
sequence:
|
|
|
- service: script.send_to_logbook
|
|
|
data:
|
|
|
topic: "CLIMATE"
|
|
|
message: "Skipping downstairs cool mode (outside temp <75F)."
|
|
|
default:
|
|
|
- service: climate.set_preset_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
preset_mode: 'none'
|
|
|
- service: climate.set_hvac_mode
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
hvac_mode: cool
|
|
|
- service: climate.set_temperature
|
|
|
data:
|
|
|
entity_id: climate.downstairs
|
|
|
temperature: 77
|
|
|
- delay: "00:20:00"
|
|
|
- service: script.set_downstairs_target_temp_based_on_conditions
|
|
|
- delay: "02:00:00" # stops it from being triggered again too soon.
|