Update blueprints/automations/bzo_climate.yaml

latest version
This commit is contained in:
2025-11-12 11:05:08 +02:00
parent 6f7514f145
commit 7102f5ec6e

View File

@@ -1,137 +1,20 @@
blueprint: blueprint:
name: BZO's Smart Climate Controller name: BZO's Smart A/C Temperature Control
description: > description: Comprehensive A/C control with automatic temperature management, presence detection, scheduling, and safety features
Automatically control a climate device based on indoor/outdoor temperatures,
using one command per update. Sends HVAC mode, temperature, and fan settings
only if different from current state. Supports external temp threshold for heat/cool switching,
presence, schedule, optional override, optional away mode, logging level, and optional window detection.
domain: automation domain: automation
input: input:
climate_entity: thermostat_section:
name: Climate Device name: Climate Unit & Sensors
description: 'Selet the unit or units that will be controled.' icon: mdi:thermostat
input:
# Core Devices
ac_unit:
name: A/C Unit
description: The climate entity for your A/C unit
selector: selector:
entity: entity:
domain: climate domain: climate
room_temp_sensor:
name: Room Temperature Sensor
description: 'Sensor or group of sensors used to calculate thermostat values.'
selector:
entity:
domain: sensor
device_class: temperature
outdoor_temp_sensor:
name: Outdoor Temperature Sensor
description: 'Used to determine HVAC mode ( cool or heat ).'
selector:
entity:
domain: sensor
device_class: temperature
presence_entity:
name: ( Optional ) Presence Sensor or Group
description: 'Used to tun off the units if house is empty.'
default: ''
selector:
entity:
domain: person
schedule_entity:
name: Schedule Helper
description: 'Schedule for the unit to run.'
selector:
entity:
domain: schedule
override_switch:
name: (Optional) Manual Override Switch
description: 'Override presence and schedule and turn on the unit.'
default: ''
selector:
entity:
domain: input_boolean
away_mode_helper:
name: (Optional) Away Mode Helper (turns off A/C)
default: ''
selector:
entity:
domain: input_boolean
window_sensor:
name: (Optional) Window Sensor
default: ''
selector:
entity:
domain: binary_sensor
delta_fan_low:
name: Temperature Delta for Mid Fan
default: 2
selector:
number:
min: 1
max: 5
step: 0.5
unit_of_measurement: °C
delta_fan_high:
name: Temperature Delta for High Fan
default: 3
selector:
number:
min: 2
max: 10
step: 0.5
unit_of_measurement: °C
external_temp_threshold:
name: External Temperature Heat/Cool Switch Threshold
default: 18
selector:
number:
min: -10
max: 35
step: 1
unit_of_measurement: °C
target_temp_helper:
name: Target Temperature Helper
description: '
Control your comfort temperature via automations or the UI, you can
specify an *[input_number](https://www.home-assistant.io/integrations/input_number/)*
entity here.
Create your helper [here](https://my.home-assistant.io/redirect/helpers/). '
selector:
entity:
domain: input_number
temp_adjust_threshold:
name: Temperature Delta Adjustment Threshold
description: 'The Delta value, representing the difference between the desired and actual temperature, will adjust the thermostat.'
default: 4
selector:
number:
min: 0
max: 10
step: 0.5
unit_of_measurement: °C
temp_adjust_amount:
name: Temperature Adjustment Amount
description: 'How many degrees to add or subtract if the difference between the desired temp and actual temp is higher than Delta.'
default: 1
selector:
number:
min: 0
max: 5
step: 0.5
unit_of_measurement: °C
fan_mode_profile: fan_mode_profile:
name: Fan Mode Profile name: Fan Mode Profile
description: 'Fan mode: Standard for Auto, High, mid, low and numerif for Auto, 1, 2, etc.' description: 'Fan mode: Standard for Auto, High, mid, low and numerif for Auto, 1, 2, etc.'
@@ -142,220 +25,619 @@
- standard - standard
- numeric - numeric
log_level: room_temperature_sensor:
name: Logging Level name: Room Temperature Sensor
default: info 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: selector:
select: select:
options: options:
- info - standard
- debug - debug
variables:
mode: restart climate_dev: !input ac_unit
max_exceeded: silent room_temperature_sensor: !input room_temperature_sensor
trigger_variables: desired_temperature_helper: !input desired_temperature_helper
override_switch: !input override_switch external_temperature_sensor: !input external_temperature_sensor
presence_entity: !input presence_entity
trigger: schedule_helper: !input schedule_helper
- platform: time_pattern override_helper: !input override_helper
minutes: "/5" window_detection_entity: !input window_detection_entity
- platform: state calibration_offset: !input calibration_offset
entity_id: !input schedule_entity cool_heat_threshold: !input cool_heat_threshold
to: "on" temp_delta_high: !input temp_delta_high
- platform: state temp_delta_low: !input temp_delta_low
entity_id: !input target_temp_helper
condition:
- condition: template
value_template: >
{{ override_switch == '' or is_state( override_switch, 'off') }}
- condition: state
entity_id: !input schedule_entity
state: "on"
# - condition: state
# entity_id: !input presence_entity
# state: "home"
# - condition: template
# value_template: >
# {% set window = window_sensor %}
# {{ window == '' or is_state(window, 'off') }}
action:
- variables:
climate: !input climate_entity
room_sensor: !input room_temp_sensor
outside_sensor: !input outdoor_temp_sensor
target_temp_entity: !input target_temp_helper
fan_profile: !input fan_mode_profile fan_profile: !input fan_mode_profile
away: !input away_mode_helper away: !input away_mode_helper
adjust_threshold: !input temp_adjust_threshold temp_control_last_check: !input temp_control_last_check_helper
adjust_amount: !input temp_adjust_amount temp_control_waiting: !input temp_control_waiting_helper
delta_low: !input delta_fan_low no_action_duration_var: !input no_action_duration
delta_high: !input delta_fan_high debug: !input debug_mode
threshold: !input external_temp_threshold
override_switch: !input override_switch
presence: !input presence_entity
log_level: !input log_level
schedule_entity: !input schedule_entity
room_temp: > no_action_duration_sec: "{{ no_action_duration_var*60 }}"
{% set r = states(room_sensor) %} ac_off: "{{ is_state(climate_dev, 'off') }}"
{{ r | float(0) if r not in ['unknown', 'unavailable'] else 0 }} 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') }}"
outside_temp: > should_cool: "{{ external_temp > cool_heat_threshold }}"
{% set o = states(outside_sensor) %} should_heat: "{{ external_temp <= cool_heat_threshold }}"
{{ o | float(999) if o not in ['unknown', 'unavailable'] else 999 }} should_be_off: >-
{% if should_cool %}
desired_temp: > {% if room_temp < (desired_temp - temp_delta_high) %}
{% set t = states(target_temp_entity) %} true
{{ t | float(22) if t not in ['unknown', 'unavailable'] else 22 }}
adjusted_temp: >
{% set delta = (room_temp - desired_temp) | abs %}
{% if delta >= adjust_threshold %}
{% if room_temp > desired_temp %}
{{ desired_temp - adjust_amount }}
{% else %} {% else %}
{{ desired_temp + adjust_amount }} false
{% endif %} {% endif %}
{% else %} {% else %}
{{ desired_temp }} {% if room_temp > (desired_temp + temp_delta_high) %}
true
{% else %}
false
{% endif %} {% endif %}
{% endif %}
hvac_mode: > hvac_mode: >-
{% if outside_temp < threshold %} heat {% if should_cool %} "cool"
{% elif outside_temp < 999 %} cool {% else %} "heat"
{% else %} auto {% endif %} {% endif %}
calibrated_temp: >-
delta: "{{ room_temp - desired_temp }}" {% if should_cool %}
{% if room_temp > desired_temp %} {{ desired_temp - calibration_offset }}
fan_mode: > {% 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 fan_profile == 'standard' %}
{% if delta | abs >= delta_high %} high {% if ( temp_delta | abs ) >= temp_delta_high %} high
{% elif delta | abs >= delta_low %} mid {% elif ( temp_delta | abs ) >= temp_delta_low %} mid
{% else %} auto {% endif %} {% else %} auto {% endif %}
{% else %} {% else %}
{% if delta | abs >= delta_high %} "5" {% if ( temp_delta | abs ) >= temp_delta_high %} 5
{% elif delta | abs >= delta_low %} "3" {% elif ( temp_delta | abs ) >= temp_delta_low %} 3
{% else %} "1" {% endif %} {% else %} auto {% endif %}
{% 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
- choose: condition: []
- conditions:
- condition: state
entity_id: !input schedule_entity
state: "off"
sequence:
- service: climate.turn_off
target:
entity_id: !input climate_entity
- service: logbook.log
data:
name: "Smart Climate"
message: "A/C turned off because schedule is OFF"
entity_id: !input climate_entity
- condition: template
value_template: >
{{ schedule_entity != 'off' }}
action:
- choose: - choose:
- conditions: - conditions:
- condition: template - condition: template
value_template: > value_template: "{{ not ac_off or ac_off}}"
{{ presence != '' and is_state(presence, 'not_home') }} - condition: template
value_template: "{{ debug == 'debug'}}"
sequence: sequence:
- service: climate.turn_off
target:
entity_id: !input climate_entity
- service: logbook.log - service: logbook.log
data: data:
name: "Smart Climate" name: "Smart Climate"
message: "A/C turned off due to absence (not_home)" message: ' Room_temp = {{ room_temp }}°C, Desired_temp = {{ desired_temp }}°C
entity_id: !input climate_entity
- condition: template
value_template: >
{{ presence == '' or is_state(presence, 'home') }}
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: - choose:
# AWAY mode - turn off A/C if on, otherwise stop
- conditions: - conditions:
- condition: template - condition: template
value_template: > value_template: >
{{ away != '' and is_state(away, 'on') }} {{ away != '' and is_state(away, 'on') }}
sequence:
- choose:
- conditions:
- condition: not
conditions:
- condition: state
entity_id: !input ac_unit
state: "off"
sequence: sequence:
- service: climate.turn_off - service: climate.turn_off
target: target:
entity_id: !input climate_entity entity_id: !input ac_unit
- service: logbook.log - service: logbook.log
data: data:
name: "Smart Climate" name: "Smart Climate"
message: "A/C turned off due to Away Mode" message: "A/C turned off due to Away Mode"
entity_id: !input climate_entity entity_id: !input ac_unit
- condition: template default:
value_template: > - stop: "Away mode active but A/C already off"
{{ away == '' or is_state(away, '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: - choose:
- conditions: - conditions:
- condition: template - condition: not
value_template: "{{ log_level == 'debug' }}" conditions:
- condition: state
entity_id: !input ac_unit
state: "off"
sequence: sequence:
- service: climate.turn_off
target:
entity_id: !input ac_unit
- service: logbook.log - service: logbook.log
data: data:
name: "Smart Climate" name: "Smart Climate"
message: > message: "A/C turned off due Nobody Home"
External temp = {{ outside_temp }}°C, Threshold = {{ threshold }}°C → Mode = {{ hvac_mode }} entity_id: !input ac_unit
entity_id: !input climate_entity default:
- stop: "Nobody Home active but A/C already off"
- stop: "Nobody Home mode active"
- service: logbook.log # Not scheduled - turn off A/C
data:
name: "Smart Climate DEBUG"
message: >
Current state = {{ states(climate) }}, HVAC = {{ state_attr(climate, 'hvac_modes') or 'unknown' }},
Temp = {{ state_attr(climate, 'temperature') }}, Fan = {{ state_attr(climate, 'fan_mode') or 'unknown' }};
Target: HVAC = {{ hvac_mode }}, Temp = {{ adjusted_temp }}, Fan = {{ fan_mode }}
entity_id: !input climate_entity
- conditions: - conditions:
- condition: template - condition: template
value_template: "{{ log_level == 'info' }}" value_template: "{{ not is_scheduled }}"
- "{{ not is_override }}"
#- "{{ not ac_off }}"
sequence: 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 - service: logbook.log
data: data:
name: "Smart Climate" name: "Smart Climate"
message: "Automation triggered (log level: info)" message: "A/C turned off due Outside schedule"
entity_id: !input climate_entity entity_id: !input ac_unit
default:
- stop: "Outside schedule active but A/C already off"
- stop: "Outside schedule mode active"
- condition: or # 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
(not should_cool 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: conditions:
- condition: template - "{{ (room_temp + 0.5) >= desired_temp and ((climate_fan_mode != state_attr(climate_dev, 'fan_mode')
value_template: > or calibrated_temp != state_attr(climate_dev, 'temperature') or ac_off)) }}"
{{ states(climate) in ['off', 'unavailable', 'unknown'] }} - condition: state
- condition: template entity_id: !input temp_control_waiting_helper
value_template: > state: 'off'
{% set state = states(climate) %} sequence:
{% set fan = (state_attr(climate, 'fan_mode') or 'unknown') | string %}
{% set temp = state_attr(climate, 'temperature') | float(999) %}
{{ state != hvac_mode or fan != fan_mode or (temp | round(1)) != (adjusted_temp | round(1)) }}
- service: climate.set_temperature - service: climate.set_temperature
target: target:
entity_id: !input climate_entity entity_id: !input ac_unit
data: data:
temperature: "{{ adjusted_temp | float }}" temperature: "{{ calibrated_temp | abs }}"
hvac_mode: "{{ hvac_mode }}" hvac_mode: cool
- choose:
# High intensity
- conditions:
- condition: template
value_template: "{{ temp_delta >= temp_delta_high }}"
sequence:
- service: climate.set_fan_mode - service: climate.set_fan_mode
target: target:
entity_id: !input climate_entity entity_id: !input ac_unit
data: data:
fan_mode: "{{ fan_mode }}" fan_mode: "{{ climate_fan_mode }}"
# Low intensity
- service: logbook.log - conditions:
- condition: template
value_template: "{{ temp_delta >= temp_delta_low }}"
sequence:
- service: climate.set_fan_mode
target:
entity_id: !input ac_unit
data: data:
name: "Smart Climate" fan_mode: "{{ climate_fan_mode }}"
message: > # Auto intensity (default)
Sent command: HVAC = {{ hvac_mode }}, Temp = {{ adjusted_temp }}°C, Fan = {{ fan_mode }} default:
entity_id: !input climate_entity - service: climate.set_fan_mode
target:
entity_id: !input ac_unit
data:
fan_mode: auto
- delay: # Heating mode
minutes: 1 - 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.set_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.set_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