Files
HA/blueprints/automations/bzo_climate.yaml
2025-11-17 09:50:06 +02:00

644 lines
22 KiB
YAML

blueprint:
name: BZO's Smart A/C Temperature Control
description: Comprehensive A/C control with automatic temperature management, presence detection, scheduling, and safety features
domain: automation
input:
thermostat_section:
name: Climate Unit & Sensors
icon: mdi:thermostat
input:
# Core Devices
ac_unit:
name: A/C Unit
description: The climate entity for your A/C unit
selector:
entity:
domain: climate
fan_mode_profile:
name: Fan Mode Profile
description: 'Fan mode: Standard for Auto, High, mid, low and numerif for Auto, 1, 2, etc.'
default: standard
selector:
select:
options:
- standard
- numeric
room_temperature_sensor:
name: Room Temperature Sensor
description: Dedicated room temperature sensor
selector:
entity:
domain: sensor
#device_class: temperature
external_temperature_sensor:
name: External Temperature Sensor
description: External temperature sensor for heat/cool mode selection
selector:
entity:
domain: sensor
device_class: temperature
helper_section:
name: Helper section
icon: mdi:sun-clock
collapsed: true
input:
# Helpers
desired_temperature_helper:
name: Desired Temperature Helper
description: Input number helper to store desired temperature
selector:
entity:
domain: input_number
schedule_helper:
name: Schedule Helper
description: Schedule helper for time-based control
selector:
entity:
domain: schedule
override_helper:
name: Override Helper
description: Boolean helper to override automatic control
selector:
entity:
domain: input_boolean
away_mode_helper:
name: (Optional) Away Mode Helper (turns off A/C)
default: ''
selector:
entity:
domain: input_boolean
temp_control_waiting_helper:
name: temp_control_waiting Helper
selector:
entity:
domain: input_boolean
temp_control_last_check_helper:
name: temp_control_last_check Helper
selector:
entity:
domain: input_datetime
presence_section:
name: Presence and Detection section
icon: mdi:sun-clock
collapsed: true
input:
window_detection_entity:
name: Window Detection Entity
description: Entity that detects if windows are open (binary_sensor) - Optional
default: ""
selector:
entity:
domain: binary_sensor
# Presence Detection
presence_entity:
name: Presence Entity
description: Entity that tracks if someone is home - Optional
default: ""
selector:
entity:
domain:
- person
- group
# Timing Configuration
home_duration:
name: Home Duration
description: Minutes to wait after arriving home before turning on A/C
default: 5
selector:
number:
min: 0
max: 60
unit_of_measurement: minutes
away_duration:
name: Away Duration
description: Minutes to wait after leaving home before turning off A/C
default: 15
selector:
number:
min: 0
max: 120
unit_of_measurement: minutes
window_reaction_time:
name: Window Reaction Time
description: Minutes to wait after window detection before taking action
default: 2
selector:
number:
min: 0
max: 30
unit_of_measurement: minutes
# off_duration_check:
# name: Off Duration Check
# description: Minutes to keep A/C off when desired temperature is reached
# default: 10
# selector:
# number:
# min: 5
# max: 60
# unit_of_measurement: minutes
no_action_duration:
name: No Action Duration
description: Minutes of no actions after A/C was turned off
default: 5
selector:
number:
min: 1
max: 30
unit_of_measurement: minutes
# restart_check_duration:
# name: Restart Check Duration
# description: Minutes to wait before checking if A/C should restart
# default: 15
# selector:
# number:
# min: 5
# max: 60
# unit_of_measurement: minutes
# Temperature Configuration
temp_delta_low:
name: Temperature Delta for Med Intensity
description: Temperature difference to trigger low fan intensity
default: 2.0
selector:
number:
min: 0.5
max: 5.0
step: 0.5
unit_of_measurement: "°C"
temp_delta_high:
name: Temperature Delta for High Intensity
description: Temperature difference to trigger high fan intensity
default: 3.0
selector:
number:
min: 1.0
max: 10.0
step: 0.5
unit_of_measurement: "°C"
calibration_offset:
name: Calibration Offset
description: Temperature offset for A/C unit calibration
default: 0.0
selector:
number:
min: -5.0
max: 5.0
step: 0.1
unit_of_measurement: "°C"
cool_heat_threshold:
name: Cool/Heat Threshold
description: External temperature threshold to switch between cooling and heating
default: 20.0
selector:
number:
min: 10.0
max: 30.0
step: 0.5
unit_of_measurement: "°C"
debug_mode:
name: Debug Mode
description: 'Set Debug mode to show values for variables.'
default: standard
selector:
select:
options:
- standard
- debug
variables:
climate_dev: !input ac_unit
room_temperature_sensor: !input room_temperature_sensor
desired_temperature_helper: !input desired_temperature_helper
external_temperature_sensor: !input external_temperature_sensor
presence_entity: !input presence_entity
schedule_helper: !input schedule_helper
override_helper: !input override_helper
window_detection_entity: !input window_detection_entity
calibration_offset: !input calibration_offset
cool_heat_threshold: !input cool_heat_threshold
temp_delta_high: !input temp_delta_high
temp_delta_low: !input temp_delta_low
fan_profile: !input fan_mode_profile
away: !input away_mode_helper
temp_control_last_check: !input temp_control_last_check_helper
temp_control_waiting: !input temp_control_waiting_helper
no_action_duration_var: !input no_action_duration
debug: !input debug_mode
no_action_duration_sec: "{{ no_action_duration_var*60 }}"
ac_off: "{{ is_state(climate_dev, 'off') }}"
room_temp: "{{ states(room_temperature_sensor) | float(0) }}"
desired_temp: "{{ states(desired_temperature_helper) | float(20) }}"
external_temp: "{{ states(external_temperature_sensor) | float(20) }}"
temp_delta: "{{ (room_temp - desired_temp) | abs }}"
is_home: "{{ presence_entity == '' or is_state(presence_entity, 'home') }}"
is_scheduled: "{{ is_state(schedule_helper, 'on') }}"
is_override: "{{ is_state(override_helper, 'on') }}"
is_window_open: "{{ window_detection_entity != '' and is_state(window_detection_entity, 'on') }}"
should_cool: "{{ external_temp > cool_heat_threshold }}"
should_heat: "{{ external_temp <= cool_heat_threshold }}"
should_be_off: >-
{% if should_cool %}
{% if room_temp < (desired_temp - temp_delta_high) %}
true
{% else %}
false
{% endif %}
{% else %}
{% if room_temp > (desired_temp + temp_delta_high) %}
true
{% else %}
false
{% endif %}
{% endif %}
hvac_mode: >-
{% if should_cool %} "cool"
{% else %} "heat"
{% endif %}
calibrated_temp: >-
{% if should_cool %}
{% if room_temp > desired_temp %} {{ desired_temp - calibration_offset }}
{% elif room_temp <= desired_temp %} {{ desired_temp }} {% endif %}
{% else %}
{% if room_temp > desired_temp %} {{ desired_temp }}
{% elif room_temp <= desired_temp %} {{ desired_temp + calibration_offset }} {% endif %}
{% endif %}
climate_fan_mode: >-
{% if fan_profile == 'standard' %}
{% if ( temp_delta | abs ) >= temp_delta_high %} high
{% elif ( temp_delta | abs ) >= temp_delta_low %} mid
{% else %} auto {% endif %}
{% else %}
{% if ( temp_delta | abs ) >= temp_delta_high %} 5
{% elif ( temp_delta | abs ) >= temp_delta_low %} 3
{% else %} auto {% endif %}
{% endif %}
ac_fan_mode: "{{ state_attr(climate_dev, 'fan_mode') }}"
trigger:
- platform: state
entity_id: !input desired_temperature_helper
id: desire_temp_change
# - platform: state
# entity_id: !input room_temperature_sensor
# id: temp_change
- platform: state
entity_id: !input schedule_helper
id: schedule_change
- platform: state
entity_id: !input override_helper
id: override_change
# - platform: state
# entity_id: !input external_temperature_sensor
# id: external_temp_change
- platform: state
entity_id: !input away_mode_helper
id: state
- platform: state
entity_id: !input temp_control_waiting_helper
to: "off"
id: temp_control_waiting_off
#Time-based trigger to handle optional entities
- platform: time_pattern
minutes: "/5"
id: periodic_check
condition: []
action:
- choose:
- conditions:
- condition: template
value_template: "{{ not ac_off or ac_off}}"
- condition: template
value_template: "{{ debug == 'debug'}}"
sequence:
- service: logbook.log
data:
name: "Smart Climate"
message: ' Room_temp = {{ room_temp }}°C, Desired_temp = {{ desired_temp }}°C
Calculated = {{ calibrated_temp }}°C → Cool = {{ should_cool }}
Fan_mode = {{ climate_fan_mode }}, AC_off = {{ ac_off }}
AC_mode = {{ states(climate_dev) }}
Temp_delta = {{ temp_delta }}, Is_Home = {{ is_home }}
date= {{ states(temp_control_last_check) | as_datetime }}, seconds: {{ (now().timestamp() - states(temp_control_last_check) | as_datetime | as_timestamp) }}
time_no_action: {{ no_action_duration_sec }}
'
entity_id: !input ac_unit
- choose:
# AWAY mode - turn off A/C if on, otherwise stop
- conditions:
- condition: template
value_template: >
{{ away != '' and is_state(away, 'on') }}
sequence:
- choose:
- conditions:
- condition: not
conditions:
- condition: state
entity_id: !input ac_unit
state: "off"
sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: logbook.log
data:
name: "Smart Climate"
message: "A/C turned off due to Away Mode"
entity_id: !input ac_unit
default:
- stop: "Away mode active but A/C already off"
- stop: "Away mode active"
# Window open - turn off A/C
- conditions:
- condition: template
value_template: "{{ is_window_open }}"
- "{{ not ac_off }}"
sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: logbook.log
data:
name: "Smart Climate"
message: "A/C turned off due to Window detected open"
entity_id: !input ac_unit
- stop: "Window detected open"
# Not home - turn off A/C
- conditions:
- condition: template
value_template: "{{ not is_home }}"
sequence:
- choose:
- conditions:
- condition: not
conditions:
- condition: state
entity_id: !input ac_unit
state: "off"
sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: logbook.log
data:
name: "Smart Climate"
message: "A/C turned off due Nobody Home"
entity_id: !input ac_unit
default:
- stop: "Nobody Home active but A/C already off"
- stop: "Nobody Home mode active"
# Not scheduled - turn off A/C
- conditions:
- condition: template
value_template: "{{ not is_scheduled }}"
- "{{ not is_override }}"
#- "{{ not ac_off }}"
sequence:
- choose:
- conditions:
- condition: not
conditions:
- condition: state
entity_id: !input ac_unit
state: "off"
sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: logbook.log
data:
name: "Smart Climate"
message: "A/C turned off due Outside schedule"
entity_id: !input ac_unit
default:
- stop: "Outside schedule active but A/C already off"
- stop: "Outside schedule mode active"
# Currently waiting - check if 10 minutes have passed
- conditions:
- condition: state
entity_id: !input temp_control_waiting_helper
state: 'on'
- condition: template
value_template: >-
{{ (now().timestamp() - states(temp_control_last_check) | as_datetime | as_timestamp) >= no_action_duration_sec }}
sequence:
- if:
- condition: template
value_template: >-
{{ (should_cool and room_temp <= desired_temp) or
(not should_cool and room_temp >= desired_temp) }}
then:
- service: input_datetime.set_datetime
target:
entity_id: !input temp_control_last_check_helper
data:
datetime: "{{ now() }}"
- if:
- condition: template
value_template: >-
{{ (should_cool and room_temp < desired_temp) or
(should_heat and room_temp > desired_temp) }}
then:
- service: input_boolean.turn_off
target:
entity_id: !input temp_control_waiting_helper
- service: logbook.log
data:
name: Temperature Control
message: >-
10-minute wait completed. Rechecking temperature: {{ room_temp }}° vs {{ desired_temp }}°
# Temperature reached target - turn off and wait
- conditions:
- condition: template
value_template: "{{ room_temp + 0.5 <= desired_temp }}"
- condition: state
entity_id: !input ac_unit
state: 'cool'
sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: input_boolean.turn_on
target:
entity_id: !input temp_control_waiting_helper
- service: input_datetime.set_datetime
target:
entity_id: !input temp_control_last_check_helper
data:
datetime: "{{ now() }}"
- service: logbook.log
data:
name: Temperature Control
message: >-
Target reached ({{ room_temp }}° vs {{ desired_temp }}° ).
Stopping unit for 10 minutes.
- stop: "Temperature control cycle"
# # Similar logic for heating mode
- conditions:
- condition: template
value_template: "{{ room_temp - 0.5 > desired_temp }}"
- condition: state
entity_id: !input ac_unit
state: 'heat'
sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: input_boolean.turn_on
target:
entity_id: !input temp_control_waiting_helper
- service: input_datetime.set_datetime
target:
entity_id: !input temp_control_last_check_helper
data:
datetime: "{{ now() }}"
- service: logbook.log
data:
name: Temperature Control
message: >-
Target reached ({{ room_temp }}° vs {{ desired_temp }}°).
Stopping unit for 10 minutes.
- stop: "Temperature control cycle"
# Main control logic
default:
- choose:
# Cooling mode
- conditions:
- condition: template
value_template: "{{ should_cool and (is_scheduled or is_override) }}"
- condition: and
conditions:
- "{{ (room_temp + 0.5) >= desired_temp and ((climate_fan_mode != state_attr(climate_dev, 'fan_mode')
or calibrated_temp != state_attr(climate_dev, 'temperature') or ac_off)) }}"
- condition: state
entity_id: !input temp_control_waiting_helper
state: 'off'
sequence:
- service: climate.set_temperature
target:
entity_id: !input ac_unit
data:
temperature: "{{ calibrated_temp | abs }}"
hvac_mode: cool
- choose:
# High intensity
- conditions:
- condition: template
value_template: "{{ temp_delta >= temp_delta_high }}"
sequence:
- service: climate.set_fan_mode
target:
entity_id: !input ac_unit
data:
fan_mode: "{{ climate_fan_mode }}"
# Low intensity
- conditions:
- condition: template
value_template: "{{ temp_delta >= temp_delta_low }}"
sequence:
- service: climate.set_fan_mode
target:
entity_id: !input ac_unit
data:
fan_mode: "{{ climate_fan_mode }}"
# Auto intensity (default)
default:
- service: climate.set_fan_mode
target:
entity_id: !input ac_unit
data:
fan_mode: auto
# Heating mode
- conditions:
- condition: template
value_template: "{{ should_heat and (is_scheduled or is_override) }}"
- condition: and
conditions:
#- states(climate_dev) != heat
- "{{ (room_temp - 0.5) <= desired_temp and (climate_fan_mode != state_attr(climate_dev, 'fan_mode')
or calibrated_temp != state_attr(climate_dev, 'temperature') or ac_off) }}"
sequence:
- service: climate.set_temperature
target:
entity_id: !input ac_unit
data:
temperature: "{{ calibrated_temp }}"
hvac_mode: heat
- choose:
# High intensity
- conditions:
- condition: template
value_template: "{{ temp_delta >= temp_delta_high }}"
sequence:
- service: "{{ climate_fan_mode }}"
target:
entity_id: !input ac_unit
data:
fan_mode: high
# Low intensity
- conditions:
- condition: template
value_template: "{{ temp_delta >= temp_delta_low }}"
sequence:
- service: "{{ climate_fan_mode }}"
target:
entity_id: !input ac_unit
data:
fan_mode: mid
# Auto intensity (default)
default:
- service: climate.set_fan_mode
target:
entity_id: !input ac_unit
data:
fan_mode: auto
# Turn off if temperature is within acceptable range
default:
- condition: template
value_template: "{{ should_be_off == true }}"
- service: climate.turn_off
target:
entity_id: !input ac_unit
mode: queued
max_exceeded: silent