Skip to main content
Selora Homes Selora Homes
Recipe · v1.0.0 · Released Aug 28, 2026

Window Open HVAC Pause

Installs a Home Assistant automation that turns the thermostat off when a window is left open, so you are not heating or cooling the street, and turns it back to the mode it was in once every window is shut. Add door sensors and a temperature sensor for the full picture.

Central heating or cooling has no idea a window is open; it just works harder to hold the setpoint against the outside air. This recipe gives it eyes. When any window you pick has been open past a short grace period, it turns the thermostat off, and once every window is shut again it puts the thermostat back to the exact mode it was running before, heating or cooling.

The grace period keeps it from reacting to a window cracked for a minute. Two minutes is the default, long enough to ignore a quick airing but short enough to catch a window that stays open. It runs entirely on your own sensors and thermostat.

Remembering the mode

The recipe does not guess how to resume. When it pauses, it records whatever mode the thermostat was in, and resuming restores that same mode, so a system in cooling comes back in cooling and one in heating comes back in heating. If it ever cannot read the saved mode, it falls back to the mode you set as the default.

Doors and the outside temperature

Add exterior door sensors as the optional door role and a patio or back door left open pauses the thermostat just like a window. Pick an outdoor temperature sensor as the optional temperature role and the notification that fires on a pause includes the current outdoor reading, so a window open on a mild day and one open in a cold snap read differently at a glance.

Files Selora AI's pipeline reads to install this recipe. The manifest declares roles, inputs, and integrations; the package files are Jinja-templated YAML applied to Home Assistant.

# Window Open HVAC Pause — turn the thermostat off while a window (or door) is
# open, and restore the mode it was in once everything is shut.
#
# One thermostat (single, so there is one saved-mode helper). Windows are
# required; exterior doors are optional and treated as openings too. On pause
# the recipe records the thermostat's current mode to an input_text helper,
# then sets it off; on resume it reads that helper back. A picked temperature
# sensor is echoed into the pause notification. The thermostat-not-off guard on
# pause keeps a second open window from overwriting the saved mode with "off".
slug: window-open-hvac-pause
version: 1.0.0
title: Window Open HVAC Pause
tagline: A window left open turns the thermostat off, and shutting every window puts it back exactly as it was.
description: >-
  Turns the thermostat off when any window has been open past a short grace
  period, and restores the exact mode it was running once every window is shut.
  Optional exterior door sensors count as openings too, and an optional outdoor
  temperature sensor is included in the pause notification.
author: Selora AI
released: "2026-08-28"
min_integration_version: "0.12.0"
tags: [climate, windows, energy-saving, thermostat]
roles:
  # Single thermostat: the recipe keeps one saved-mode helper, so it targets
  # one thermostat (run the recipe again for another zone). kind climate.
  - id: thermostat
    title: Thermostat
    kind: climate
    min_count: 1
    max_count: 1
    selection: required
    description: >-
      The thermostat to pause and resume. The recipe remembers the mode it was
      in and restores it when the windows are shut.
  # Window contact sensors — multi-select. binary_sensor + device_class window.
  # min_count 1.
  - id: windows
    title: Window sensors
    kind: binary_sensor
    device_class: window
    min_count: 1
    selection: required
    description: >-
      The window contact sensors that pause the thermostat. Any one open past
      the grace period pauses it.
  # Optional exterior door sensors treated as openings. device_class door.
  - id: doors
    title: Door sensors
    kind: binary_sensor
    device_class: door
    min_count: 0
    selection: required
    description: >-
      Optional. Exterior door sensors, a patio or back door, that pause the
      thermostat the same way a window does. Leave empty to watch windows only.
  # Optional outdoor temperature sensor echoed into the pause notification.
  - id: temperature
    title: Outdoor temperature sensor
    kind: sensor
    device_class: temperature
    min_count: 0
    max_count: 1
    selection: required
    description: >-
      Optional. An outdoor temperature sensor whose reading is included in the
      notification when the thermostat pauses. Leave empty for a plain
      notification.
inputs:
  # Grace period, in minutes, a window may be open before the pause. 2 minutes
  # ignores a quick airing but catches a window that stays open.
  - id: open_minutes
    type: number
    label: Grace period (minutes)
    description: >-
      How long a window may be open before the thermostat pauses.
    default: 2
    min: 0
    max: 120
  # Fallback mode for resume when the saved mode cannot be read (for example a
  # restart cleared the helper). heat_cool suits most systems that both heat
  # and cool.
  - id: default_mode
    type: select
    label: Fallback mode
    description: >-
      The mode to resume in if the saved mode cannot be read.
    default: "heat_cool"
    choices: ["heat_cool", "heat", "cool", "auto"]
package_files:
  - package/helpers/pause_state.yaml.j2
  - package/automations/pause.yaml.j2
{# Window Open HVAC Pause: one automation pauses the thermostat when an opening
   is left open, one resumes it when everything is shut.

   Pause records the thermostat's current mode to the helper, sets it off, and
   raises a "paused by us" flag. The "not already off" condition means a second
   window opening while paused cannot overwrite the saved mode with "off".
   Resume waits for every opening to be shut and that flag to be on (so it only
   resumes a pause it caused, never a thermostat the homeowner turned off
   themselves), restores the saved mode, falling back to the default mode if
   the helper is empty, then clears the flag. Windows and any optional doors are
   treated the same. #}
{% set su = slug | replace('-', '_') %}
{% set openings = roles.windows + roles.doors %}
{% set thermo = roles.thermostat[0] %}
{% set saved = 'input_text.' ~ su ~ '_saved_mode' %}
{% set paused = 'input_boolean.' ~ su ~ '_paused' %}
automation:
  - id: selora_recipe_{{ su }}_pause
    alias: "Window Open HVAC Pause: pause"
    description: >-
      When any window or door has been open past the grace period, save the
      thermostat's mode and switch it off.
    mode: single
    trigger:
{% for opening in openings %}
      - platform: state
        entity_id: {{ opening }}
        to: "on"
        for:
          minutes: {{ inputs.open_minutes }}
{% endfor %}
    condition:
      - condition: template
        value_template: "{% raw %}{{ not is_state('{% endraw %}{{ thermo }}{% raw %}', 'off') }}{% endraw %}"
    action:
      - service: input_text.set_value
        target:
          entity_id: {{ saved }}
        data:
          value: "{% raw %}{{ states('{% endraw %}{{ thermo }}{% raw %}') }}{% endraw %}"
      - service: climate.set_hvac_mode
        target:
          entity_id: {{ thermo }}
        data:
          hvac_mode: "off"
      - service: input_boolean.turn_on
        target:
          entity_id: {{ paused }}
      - service: notify.notify
        data:
          title: "Heating and cooling paused"
{% if roles.temperature %}
          message: "{% raw %}A window or door has been open for a while, so heating and cooling is paused. It is {{ states('{% endraw %}{{ roles.temperature[0] }}{% raw %}') }}{{ state_attr('{% endraw %}{{ roles.temperature[0] }}{% raw %}', 'unit_of_measurement') }} outside. It will resume when everything is shut.{% endraw %}"
{% else %}
          message: "A window or door has been open for a while, so heating and cooling is paused. It will resume when everything is shut."
{% endif %}
  - id: selora_recipe_{{ su }}_resume
    alias: "Window Open HVAC Pause: resume"
    description: >-
      Once every window and door is shut, restore the thermostat to the mode it
      was in before the pause.
    mode: single
    trigger:
{% for opening in openings %}
      - platform: state
        entity_id: {{ opening }}
        to: "off"
{% endfor %}
      # Also re-check on startup. Resume is otherwise driven purely by an
      # opening closing, so a window shut while Home Assistant was down leaves
      # no edge to fire on and the thermostat stays off indefinitely with the
      # flag still raised. The conditions below are the same either way.
      - platform: homeassistant
        event: start
    condition:
      - condition: state
        state: "off"
        entity_id:
{% for opening in openings %}
          - {{ opening }}
{% endfor %}
      - condition: state
        entity_id: {{ paused }}
        state: "on"
    action:
      - service: climate.set_hvac_mode
        target:
          entity_id: {{ thermo }}
        data:
          hvac_mode: "{% raw %}{% set m = states('{% endraw %}{{ saved }}{% raw %}') %}{{ m if m not in ['', 'unknown', 'unavailable', 'off'] else '{% endraw %}{{ inputs.default_mode }}{% raw %}' }}{% endraw %}"
      - service: input_boolean.turn_off
        target:
          entity_id: {{ paused }}
{# Window Open HVAC Pause helpers: a text helper that remembers the
   thermostat's mode while it is paused, and a boolean flag marking that the
   recipe is the one that paused it. The pause automation writes the mode and
   raises the flag before switching the thermostat off; the resume automation
   reads the mode back and only acts while the flag is on, so it never turns on
   a thermostat the homeowner switched off themselves. Both survive a restart,
   and the resume automation re-checks them on startup, so a pause still lifts
   even when the window was shut while Home Assistant was down. #}
input_text:
  {{ slug | replace('-', '_') }}_saved_mode:
    name: "Window HVAC Pause: saved thermostat mode"
    max: 20
    icon: mdi:thermostat
input_boolean:
  {{ slug | replace('-', '_') }}_paused:
    name: "Window HVAC Pause: paused by recipe"
    icon: mdi:pause-octagon

Type to search across

↑↓ navigate ↵ open
⌘K search