Skip to content

Instantly share code, notes, and snippets.

@danieleparazza
Forked from raffy-ops/hvac_pause.yaml
Last active February 10, 2026 10:19
Show Gist options
  • Select an option

  • Save danieleparazza/0342467484089d815152d274408bcab1 to your computer and use it in GitHub Desktop.

Select an option

Save danieleparazza/0342467484089d815152d274408bcab1 to your computer and use it in GitHub Desktop.
HA HVAC Pause Blueprint V2
#ver. 2.0.0
blueprint:
name: HVAC Pause V2.0.0
description: Pauses HVAC when windows/doors open; resumes full previous state once closed (with wait-for-confirmed state)
domain: automation
input:
climate_device:
name: Climate Device
description: Climate entity used for climate control.
selector:
entity:
domain: [climate]
doors_windows:
name: Door and Window Sensors
description: Group of entities that trigger pause when opened. ('on' = open)
selector:
entity:
domain: [group, binary_sensor]
pause_delay:
name: Pause Delay
description: Time to wait before pausing the HVAC system.
default:
hours: 0
minutes: 5
seconds: 0
selector:
duration: {}
resume_delay:
name: Resume Delay
description: Time to wait before resuming the HVAC system.
default:
hours: 0
minutes: 0
seconds: 30
selector:
duration: {}
timeout:
name: Timeout (optional)
description: If set, HVAC will remain off if window/door stays open. Set to 0 to disable.
default:
hours: 0
minutes: 0
seconds: 0
selector:
duration: {}
action_first:
name: Action First
description: Run pause actions before pausing HVAC?
selector:
boolean: {}
pause_action:
name: Pause Action (Optional)
default: []
selector:
action: {}
resume_action:
name: Resume Action (Optional)
default: []
selector:
action: {}
timeout_action:
name: Timeout Action (Optional)
default: []
selector:
action: {}
mode: single
variables:
action_first: !input action_first
pause_action: !input pause_action
resume_action: !input resume_action
timeout_action: !input timeout_action
climate_device: !input climate_device
doors_windows: !input doors_windows
timeout: !input timeout
timeout_empty: {"hours": 0, "minutes": 0, "seconds": 0}
trigger:
- platform: state
entity_id: !input doors_windows
from: "off"
to: "on"
for: !input pause_delay
id: group_open
condition:
- condition: not
conditions:
- condition: state
entity_id: !input climate_device
state: "off"
action:
- variables:
hvac_mode_prev: "{{ states(climate_device) }}"
temperature_prev: "{{ state_attr(climate_device, 'temperature') }}"
preset_mode_prev: "{{ state_attr(climate_device, 'preset_mode') }}"
fan_mode_prev: "{{ state_attr(climate_device, 'fan_mode') }}"
swing_mode_prev: "{{ state_attr(climate_device, 'swing_mode') }}"
temp_low_prev: "{{ state_attr(climate_device, 'target_temp_low') }}"
temp_high_prev: "{{ state_attr(climate_device, 'target_temp_high') }}"
- choose:
- conditions: "{{ pause_action | length > 0 and action_first == true }}"
sequence: !input pause_action
- service: climate.set_hvac_mode
data:
hvac_mode: "off"
target:
entity_id: !input climate_device
- choose:
- conditions: "{{ pause_action | length > 0 and action_first != true }}"
sequence: !input pause_action
- if:
- condition: template
value_template: "{{ timeout != timeout_empty }}"
then:
- wait_for_trigger:
- platform: state
entity_id: !input doors_windows
from: "on"
to: "off"
for: !input resume_delay
continue_on_timeout: true
timeout: !input timeout
- if:
- condition: template
value_template: "{{ wait.trigger == none }}"
then:
- if:
- condition: template
value_template: "{{ timeout_action | length > 0 }}"
then:
- sequence: !input timeout_action
- stop: ""
else:
- wait_for_trigger:
- platform: state
entity_id: !input doors_windows
from: "on"
to: "off"
for: !input resume_delay
continue_on_timeout: false
- condition: state
entity_id: !input climate_device
state: "off"
- service: climate.set_hvac_mode
data:
hvac_mode: "{{ hvac_mode_prev }}"
target:
entity_id: !input climate_device
- wait_for_trigger:
- platform: state
entity_id: !input climate_device
from: "off"
timeout: "00:00:30"
continue_on_timeout: true
- choose:
- conditions: "{{ temperature_prev is number and temperature_prev != state_attr(climate_device, 'temperature') }}"
sequence:
- service: climate.set_temperature
data:
temperature: "{{ temperature_prev }}"
target:
entity_id: !input climate_device
- wait_for_trigger:
- platform: template
value_template: "{{ state_attr(climate_device, 'temperature') == temperature_prev }}"
timeout: "00:00:15"
continue_on_timeout: true
- choose:
- conditions: "{{ temp_low_prev is number and temp_high_prev is number and (temp_low_prev != state_attr(climate_device, 'target_temp_low') or temp_high_prev != state_attr(climate_device, 'target_temp_high')) }}"
sequence:
- service: climate.set_temperature
data:
target_temp_low: "{{ temp_low_prev }}"
target_temp_high: "{{ temp_high_prev }}"
target:
entity_id: !input climate_device
- wait_for_trigger:
- platform: template
value_template: >
{{ state_attr(climate_device, 'target_temp_low') == temp_low_prev and
state_attr(climate_device, 'target_temp_high') == temp_high_prev }}
timeout: "00:00:15"
continue_on_timeout: true
- choose:
- conditions: "{{ preset_mode_prev is string and preset_mode_prev != state_attr(climate_device, 'preset_mode') }}"
sequence:
- service: climate.set_preset_mode
data:
preset_mode: "{{ preset_mode_prev }}"
target:
entity_id: !input climate_device
- wait_for_trigger:
- platform: template
value_template: "{{ state_attr(climate_device, 'preset_mode') == preset_mode_prev }}"
timeout: "00:00:15"
continue_on_timeout: true
- choose:
- conditions: "{{ fan_mode_prev is string and fan_mode_prev != state_attr(climate_device, 'fan_mode') }}"
sequence:
- service: climate.set_fan_mode
data:
fan_mode: "{{ fan_mode_prev }}"
target:
entity_id: !input climate_device
- wait_for_trigger:
- platform: template
value_template: "{{ state_attr(climate_device, 'fan_mode') == fan_mode_prev }}"
timeout: "00:00:15"
continue_on_timeout: true
- choose:
- conditions: "{{ swing_mode_prev is string and swing_mode_prev != state_attr(climate_device, 'swing_mode') }}"
sequence:
- service: climate.set_swing_mode
data:
swing_mode: "{{ swing_mode_prev }}"
target:
entity_id: !input climate_device
- wait_for_trigger:
- platform: template
value_template: "{{ state_attr(climate_device, 'swing_mode') == swing_mode_prev }}"
timeout: "00:00:15"
continue_on_timeout: true
- choose:
- conditions: "{{ resume_action | length > 0 }}"
sequence: !input resume_action
@danieleparazza
Copy link
Author

🔄 HVAC Pause Blueprint – Changelog v1.7.1 → v2.0.0

This changelog explains the key improvements and structural changes introduced in version 2.0.0 of the HVAC Pause blueprint compared to version 1.7.1.


✅ Major Improvements in v2.0.0

1. Manual State Snapshot (No More scene.create)

  • v1.7.1 used scene.create to store HVAC state.
  • v2.0.0 saves state manually via Jinja variables:
    • hvac_mode (via states())
    • temperature
    • target_temp_low, target_temp_high
    • preset_mode, fan_mode, swing_mode
  • 🔄 Enables full state restoration on devices that don’t support scene.create well (e.g. Samsung SmartThings).

2. Conditional Restore Logic

  • Only updates a parameter if it differs from the current state.
  • Prevents redundant commands and avoids unnecessary device toggling.

3. Reliable State Change Confirmation

  • Each climate.set_* action is followed by a wait_for_trigger to ensure the change is reflected in the entity’s state.
  • Example: after setting preset_mode, waits for the preset_mode attribute to update.

4. Null-safe Compatibility

  • All parameters are checked with is number or is string before setting.
  • Prevents errors like:
    expected float for dictionary value @ data['target_temp_low']
    

5. Wait-for-Resumed HVAC State

  • After resuming HVAC via climate.set_hvac_mode, the automation waits until the climate entity’s state is no longer off before proceeding.

🛠 Best Use Cases

  • SmartThings devices (Samsung WindFree ACs)
  • MQTT or custom climate platforms
  • Any system where full state restoration is required and scene.create is insufficient

@skycamel
Copy link

Thank you for sharing your blueprint. Just to give you some context, this will be used in a rental holiday home thus not by myself.
Everything is working fine, however I have some specific issues.
-When the AC is started while door or windows are open this automation is never triggered. Problem is that it triggers on a change of state and not on a permanent state. Is there any possibility to have a trigger for a permanent state to avoid this?

  • After the automation is triggered then you can just restart the AC with the remote control despite door or windows being open. I guess there's no way around that to prevent this but if at least the automation would be triggered on a permanent state "open" it would then switch off again after the set timeout. Renters might not care about energy consumption so that's why I would need this automation. Cheers, Luc

@danieleparazza
Copy link
Author

An additional trigger on AC state change could be added with a dedicated path for forcing it off after few seconds

@skycamel
Copy link

Thanks for your reply. And yes, I also came up with this solution unfortunately that doesn't work because my Daikin AC only has Fan/cool/auto/heat... mode but not On of Off state. When using the on/off button on the remote it doesn't change mode, only state from off to on. This on/off state is not available in the Daikin integration. When I use the "remote" on my HA dashboard then it works if you click on "Heat" which triggers a mod change (even when the previous mode was Heat) Any other ideas? I'm thinking maybe using current detection and use this as a trigger. Cheers, Luc

@danieleparazza
Copy link
Author

If mode is the only sensor that your integration exposes, then you would need an external sensor to detect whether the AC is on or off. Perhaps a power sensor or a window/door sensor on the blades, I know it sounds sketchy but you could organize everything inside a generic_thermostat template entity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment