Update ha-smart-thermostat-control.yaml

manual adjustments are out
This commit is contained in:
Andreas Gammelgaard Damsbo 2025-12-05 12:19:01 +01:00
parent 284e428e0c
commit fc3a572171

View file

@ -2,11 +2,9 @@ blueprint:
name: "Smart Thermostat Controller"
author: Andreas Gammelgaard Damsbo
description: |
Advanced thermostat automation with window/door sensors, presence detection, time schedules, and holiday calendar integration.
SETUP REQUIRED:
1. Create an input_boolean helper (Settings > Devices & Services > Helpers > Toggle) for manual override tracking
2. Create a timer helper (Settings > Devices & Services > Helpers > Timer) for override duration
Smart thermostat automation based on window/door sensors, outside temperature (winter mode), time schedules, and holiday calendar integration.
* **Day Temperature is now controlled by a separate Input Number Helper.**
domain: automation
source_url: https://gdamsbo.dk/forgejo/andreas/ha-smart-thermostat-control/raw/branch/main/ha-smart-thermostat-control.yaml
input:
@ -18,33 +16,6 @@ blueprint:
domain:
- climate
multiple: true
manual_override_helper:
name: Manual Override Helper
description: Select an input_boolean helper to track manual temperature overrides. Create one in Settings > Devices & Services > Helpers.
selector:
entity:
domain:
- input_boolean
multiple: false
override_timer:
name: Override Timer
description: Select a timer helper to manage override duration. Create one in Settings > Devices & Services > Helpers > Timer.
selector:
entity:
domain:
- timer
multiple: false
override_duration:
name: Manual Override Duration
description: 'How long manual temperature changes should override the schedule. This sets the timer duration. (Default = 120 minutes)'
default: 120
selector:
number:
mode: box
min: 30.0
max: 480.0
unit_of_measurement: minutes
step: 30.0
window_sensor:
name: Window / Door Sensor Group
description: Select your grouped or single window / door sensor.
@ -102,16 +73,14 @@ blueprint:
domain:
- schedule
multiple: false
day_temp:
name: Day Time Temperature Target
default: 21
day_temp_helper:
name: Day Time Temperature Input Number
description: Select an input_number helper that stores the desired Day Time temperature. (Create one in Settings > Devices & Services > Helpers).
selector:
number:
step: 0.5
min: 10.0
max: 30.0
unit_of_measurement: °C or °F
mode: slider
entity:
domain:
- input_number
multiple: false
night_temp:
name: Night Time Temperature Target
default: 18
@ -175,17 +144,8 @@ trigger:
entity_id: !input schedule_helper
id: schedule_change
- platform: state
entity_id: !input thermostat
attribute: temperature
id: manual_adjustment
- platform: state
entity_id: !input manual_override_helper
to: 'off'
id: override_expired
- platform: state
entity_id: !input override_timer
to: 'idle'
id: timer_finished
entity_id: !input day_temp_helper # Trigger when the input number changes
id: day_temp_change
- platform: calendar
event: end
entity_id: !input away_calendar
@ -205,86 +165,23 @@ trigger:
variables:
thermostat_entities: !input thermostat
triggered_thermostat: "{{ trigger.entity_id | default('none') }}"
# Access temperature safely:
# 1. Get the 'to_state', defaulting to a simple object/dict if missing.
# 2. Get the 'attributes' from that object, defaulting to a dict if missing.
# 3. Get the 'temperature' from the attributes, defaulting to 0, then convert to float.
new_temperature: >
{{ trigger.to_state.attributes.temperature | default(0) | float(0)
if trigger.to_state is defined and trigger.to_state.attributes is defined
else 0 }}
old_temperature: >
{{ trigger.from_state.attributes.temperature | default(0) | float(0)
if trigger.from_state is defined and trigger.from_state.attributes is defined
else 0 }}
override_helper: !input manual_override_helper
override_duration_id: !input override_duration
day_temp_input: !input day_temp
night_temp_input: !input night_temp
away_temp_input: !input away_temp
# Entity ID variables for safe templating in action conditions
schedule_helper_id: !input schedule_helper
away_calendar_id: !input away_calendar
# --- REVISED VARIABLE: Get state value from helper ---
day_temp_input: "{{ states(!input day_temp_helper) | float(21) }}"
# --- END REVISED VARIABLE ---
night_temp_input: !input night_temp
away_temp_input: !input away_temp
condition: []
action:
- choose:
# Priority 0: Manual Adjustment - Detect and enable override
- conditions:
- condition: trigger
id: manual_adjustment
# Only if temperature actually changed
- condition: template
value_template: "{{ (new_temperature - old_temperature) | abs > 0.1 }}"
# Only if the new temp is different from current schedule targets
- condition: template
value_template: >
{% if is_state(away_calendar_id, 'on') %}
{{ (new_temperature - away_temp_input) | abs > 0.1 }}
{% elif is_state(schedule_helper_id, 'on') %}
{{ (new_temperature - day_temp_input) | abs > 0.1 }}
{% else %}
{{ (new_temperature - night_temp_input) | abs > 0.1 }}
{% endif %}
sequence:
- service: logbook.log
data:
name: Smart Thermostat
message: 'Manual Override: {{ triggered_thermostat }} changed to {{ new_temperature }}°, syncing others'
# Sync temperature to all other thermostats
- repeat:
for_each: "{{ thermostat_entities | reject('eq', triggered_thermostat) | list }}"
sequence:
- service: climate.set_temperature
target:
entity_id: "{{ repeat.item }}"
data:
temperature: "{{ new_temperature }}"
# Enable manual override mode
- service: input_boolean.turn_on
target:
entity_id: !input manual_override_helper
# Start timer
- service: timer.start
target:
entity_id: !input override_timer
data:
duration: "{{ (override_duration_id * 60) | int }}"
# Priority 0b: Timer Finished - Disable override and resume schedule
- conditions:
- condition: trigger
id: timer_finished
sequence:
- service: input_boolean.turn_off
target:
entity_id: !input manual_override_helper
- service: logbook.log
data:
name: Smart Thermostat
message: 'Manual Override: Timer expired, resuming schedule'
# Priority 1: Windows/Doors Open - Turn OFF heating (overrides manual)
# Priority 1: Windows/Doors Open - Turn OFF heating
- conditions:
- condition: state
entity_id: !input window_sensor
@ -294,18 +191,12 @@ action:
- service: climate.turn_off
target:
entity_id: !input thermostat
- service: input_boolean.turn_off
target:
entity_id: !input manual_override_helper
- service: timer.cancel
target:
entity_id: !input override_timer
- service: logbook.log
data:
name: Smart Thermostat
message: 'Heating OFF: Window or door is open'
# Priority 2: Too Warm Outside - Turn OFF heating (overrides manual)
# Priority 2: Too Warm Outside - Turn OFF heating
- conditions:
- condition: numeric_state
entity_id: !input outdoor
@ -314,29 +205,12 @@ action:
- service: climate.turn_off
target:
entity_id: !input thermostat
- service: input_boolean.turn_off
target:
entity_id: !input manual_override_helper
- service: timer.cancel
target:
entity_id: !input override_timer
- service: logbook.log
data:
name: Smart Thermostat
message: 'Heating OFF: Outside temperature above threshold'
# Priority 3: Manual Override Active - Do nothing, keep manual temperature
- conditions:
- condition: state
entity_id: !input manual_override_helper
state: 'on'
sequence:
- service: logbook.log
data:
name: Smart Thermostat
message: 'Manual override active - maintaining user-set temperature'
# Priority 4: Away/Holiday Mode - Set to away temperature
# Priority 3: Away/Holiday Mode - Set to away temperature
- conditions:
- condition: state
entity_id: !input away_calendar
@ -360,7 +234,7 @@ action:
name: Smart Thermostat
message: 'Away Mode: Heating set to away temperature'
# Priority 5: Schedule Day Time - Set to day temperature
# Priority 4: Schedule Day Time - Set to day temperature
- conditions:
- condition: state
entity_id: !input schedule_helper
@ -380,14 +254,16 @@ action:
target:
entity_id: !input thermostat
data:
temperature: !input day_temp
# --- REVISED ACTION: Use the variable which holds the helper state ---
temperature: "{{ day_temp_input }}"
# --- END REVISED ACTION ---
hvac_mode: heat
- service: logbook.log
data:
name: Smart Thermostat
message: 'Day Mode: Heating set to day temperature'
message: 'Day Mode: Heating set to dynamic day temperature'
# Priority 6: Schedule Night Time - Set to night temperature
# Priority 5: Schedule Night Time - Set to night temperature
- conditions:
- condition: state
entity_id: !input schedule_helper
@ -424,5 +300,5 @@ action:
name: Smart Thermostat
message: 'Heating OFF: No active heating conditions met'
mode: single
mode: restart
max_exceeded: silent