Researched from current Home Assistant documentation on October 16, 2026. The worked timeline is illustrative; no thermostat, heating installation or live Home Assistant system was tested. Menu labels may differ on older releases. The cover is generated editorial imagery.

Use a lower target, with a clear way back

A Home Assistant window-open heating routine needs a rule for both opening and closing. For one independently controlled room, a useful starting point is two editable targets: normal and window-open. After the contact has stayed open for two minutes, select the lower target. After it has stayed closed for two minutes, select the current normal target.

This example deliberately keeps the thermostat in Heat mode. A lower target is called a setback. It may reduce the request for heat, but the thermostat can still heat if the room falls below that target. Heat mode itself does not mean the equipment is actively heating; Home Assistant reports those separately in its Climate documentation.

Use this only where the thermostat controls the room you intend. A hallway thermostat may govern the whole house. If the equipment manufacturer discourages short setbacks, or you cannot confirm suitable limits, use a window reminder instead. Keep frost protection and equipment cycling protections in the thermostat or heating controller.

1. Check the room, contact and thermostat

An entity is a named value or control in Home Assistant. You need one existing window-contact entity and one working room thermostat entity. This is a setup guide for equipment you already have, not a compatibility guarantee.

  1. Inspect the contact in Settings → Tools → States (Developer tools → States on older versions). A window contact normally stores on for open and off for closed. Confirm the mapping from normal use; unknown and unavailable are neither. See the binary-sensor states.
  2. Inspect the thermostat’s mode, target, units and limits. This recipe requires heat, a single numeric temperature target, and numeric min_temp/max_temp attributes. It does not handle Auto, cooling, or a Heat/Cool target range. The climate entity reference explains these capabilities.
  3. Use a thermostat whose target adjustment already works in Home Assistant. The set-temperature action is model-dependent. This example omits hvac_mode, so it does not request a change of mode.
  4. Identify every schedule or automation that writes that target. Before live use, consolidate those writes. Do not run this alongside a vendor schedule or another automation that repeatedly overwrites the thermostat.

For a weekly plan, the existing Home Assistant heating-schedule guide explains the timetable. Here, a schedule should update the normal-temperature helper, leaving this one automation to select the final thermostat target.

2. Add the four household controls

Under Settings → Devices & services → Helpers → Create helper, create two Toggle helpers and two Number helpers. A helper stores a setting; creating it does not control heating. Put all four on an editable dashboard beside the thermostat.

Swipe the table sideways to read all columns.

HelperExample entity IDStarting setting
Office window controlinput_boolean.office_window_controlOff until the configuration is ready; on allows evaluation.
Office window previewinput_boolean.office_window_previewOn. Keep it on throughout the rehearsal.
Office normal temperatureinput_number.office_normal_temperatureYour normal room target.
Office window temperatureinput_number.office_window_temperatureAn agreed lower target suitable for the room and equipment.

Set both Number helpers to the thermostat’s displayed unit, supported step and an appropriate bounded range. The code does not convert Celsius to Fahrenheit. A unit label alone does not convert a number. Set the actual values before enabling the routine. The example timeline uses 20°C and 16°C only to explain the logic; these are not universal safe temperatures.

Keep the Toggle helpers’ startup behavior at Restore previous state. If your version offers a startup choice, check it explicitly. Home Assistant documents the Toggle settings and Number settings and restoration. Verify each actual entity ID; the names above are examples.

3. Add one automation, with preview still on

Go to Settings → Automations & scenes → Create automation → Create new automation, open the menu, and choose Edit in YAML. Replace the editor contents with this single automation. Replace every example entity ID, including the dotted contact reference in the stability check.

It checks the window on changes, at startup, and once a minute. The contact must have held its current state for at least 120 seconds. The minute check means the decision is normally made on the first check after that threshold; this is not a measured response-time promise. There is no long-running wait to resume after a restart. Home Assistant’s trigger documentation describes these trigger types.

Scroll the code sideways to read long lines. On a keyboard, focus the code box and use the arrow keys.

alias: Office window-aware heating
mode: restart
triggers:
  - trigger: state
    entity_id:
      - binary_sensor.office_window
      - input_boolean.office_window_control
      - input_boolean.office_window_preview
      - input_number.office_normal_temperature
      - input_number.office_window_temperature
      - climate.office
  - trigger: homeassistant
    event: start
  - trigger: time_pattern
    minutes: "/1"
conditions:
  - condition: state
    entity_id: input_boolean.office_window_control
    state: "on"
  - condition: state
    entity_id: climate.office
    state: "heat"
  - condition: template
    value_template: >-
      {{ states('input_boolean.office_window_preview') in ['on', 'off']
         and states('binary_sensor.office_window') in ['on', 'off'] }}
  - condition: template
    value_template: >-
      {{ (now() - states.binary_sensor.office_window.last_changed)
         .total_seconds() >= 120 }}
  - condition: template
    value_template: >-
      {% set normal = states('input_number.office_normal_temperature') %}
      {% set setback = states('input_number.office_window_temperature') %}
      {% set low = state_attr('climate.office', 'min_temp') %}
      {% set high = state_attr('climate.office', 'max_temp') %}
      {{ is_number(normal) and is_number(setback)
         and is_number(low) and is_number(high)
         and is_number(state_attr('climate.office', 'temperature'))
         and low | float <= setback | float <= normal | float <= high | float }}
actions:
  - variables:
      target_temperature: >-
        {{ states('input_number.office_window_temperature') | float
           if is_state('binary_sensor.office_window', 'on')
           else states('input_number.office_normal_temperature') | float }}
  - choose:
      - conditions:
          - condition: state
            entity_id: input_boolean.office_window_preview
            state: "on"
        sequence:
          - action: persistent_notification.create
            data:
              notification_id: office_window_preview
              title: Office heating preview
              message: >-
                Window state: {{ states('binary_sensor.office_window') }}.
                Proposed target: {{ target_temperature }}.
                Checked: {{ now().strftime('%H:%M:%S') }}.
                No thermostat command sent.
      - conditions:
          - condition: state
            entity_id: input_boolean.office_window_preview
            state: "off"
          - condition: template
            value_template: >-
              {{ (state_attr('climate.office', 'temperature') | float
                  - target_temperature | float) | abs > 0.01 }}
        sequence:
          - action: climate.set_temperature
            target:
              entity_id: climate.office
            data:
              temperature: "{{ target_temperature }}"

The numeric guard rejects missing readings, reversed targets and targets beyond the reported thermostat limits. The later comparison avoids resending an already reported target. It cannot prove that the valve or heating system physically acted. A slow or failed integration may cause another attempt on the next check.

Preview updates one notification with a time stamp inside Home Assistant, using a fixed notification ID. It is not a phone push alert. If a condition blocks a run, the old preview can remain visible: use its time stamp and the automation’s Traces to distinguish an old message from a new decision.

4. Rehearse without opening a window or changing heat

Create one extra Toggle helper called Office practice window, with no connection to other automations. In this automation only, temporarily replace every binary_sensor.office_window with input_boolean.office_practice_window, including the dotted reference states.input_boolean.office_practice_window.last_changed.

  1. Leave Preview on, turn Control on, and set the practice window off. With the thermostat already in Heat mode and valid settings, wait for two minutes of stable state and the next minute check. Expect a notification proposing the normal target, with no thermostat change. If the real thermostat is Off, expect a blocked trace; do not turn heating on just to run a test.
  2. Turn the practice window on. After the same stability period, expect the lower target in the updated preview. Briefly switching it on and back off should not produce a lower-target decision.
  3. While it remains on, change the normal helper to another suitable value. The proposed target should remain the lower one. Turn the practice window off; after the stability period, expect the new normal target.
  4. Turn Control off, change the practice window, and wait. The preview time stamp should stop advancing. The thermostat must remain unchanged throughout this rehearsal.

Let the helper changes and minute checks trigger the automation normally. Do not use Run actions to verify the safeguards: that button skips the top-level conditions, as the automation troubleshooting documentation explains. Use ordinary helper toggles; do not fabricate a thermostat state with the Tools screen, disconnect equipment or interrupt heating protections.

What “resume” means in this example

Assume valid readings, Heat mode, Control on and Preview on. These are expected decisions from the code, not results measured in a house.

Swipe the table sideways to read all columns.

EventNormal / lower targetExpected decision
Window reported closed and stable20°C / 16°CPropose 20°C.
Window opens for 40 seconds, then closes20°C / 16°CNo 16°C decision; opening never reaches two minutes.
Window stays open for two minutes20°C / 16°CPropose 16°C on the next evaluation.
Household changes normal target while window is open19°C / 16°CContinue proposing 16°C.
Window closes and stays closed for two minutes19°C / 16°CPropose 19°C, not the earlier 20°C.
Contact becomes unavailable19°C / 16°CNo new command or preview update. Inspect the contact and current thermostat target.

After a Home Assistant restart, evaluation begins again when the entities are available and the contact satisfies the stability check. It does not need a remembered “before the window opened” snapshot. During downtime, the last thermostat target may remain in place—including the lower target. This automation is a convenience layer, not frost protection or an independent heating controller.

5. Hand control over deliberately

Turn Control off, restore the real contact ID everywhere, and save. Keep Preview on and Control on while observing the real contact during normal use. Confirm its reported state, thermostat units and proposed targets before turning Preview off for a supervised trial.

Once live, change the normal helper to request a different room temperature. To use the thermostat directly, turn Control off first, then set the thermostat yourself. Otherwise the next evaluation can overwrite a manual target. Turning Control off or Preview on does not undo a target already sent. Re-enabling Control selects the target appropriate to the current window state. The manual-override guide explains how to make that handoff visible to everyone.

If the result is unexpected

Swipe the table sideways to read all columns.

SymptomCheck firstNext step
No new previewControl, Heat mode, contact stability, numeric helpers and entity IDsRead the blocked condition in Traces. An old notification is not evidence of a fresh run.
Target returns to a different valueA vendor schedule or second automationChoose one target writer. Route the desired schedule into the normal helper.
Room still receives heatRoom temperature versus the lower target; actual equipment behaviorA setback is not an Off command. Check the model’s behavior without disabling its protections.
Heating does not resume after closingContact report, Control toggle, thermostat mode and availabilityUse normal thermostat controls if needed. The code deliberately does nothing in Off or with missing readings.
Window is open but Home Assistant says closedContact placement, battery and integration reportingFix the sensor before relying on the automation. A stable value can still be stale.

Common questions

Can I use this for two windows in the same room?

Do not duplicate the automation for the same thermostat: the closed window could restore heat while the other stays open. A multi-window version needs one combined decision: lower the target if any valid contact is open, resume only when all are closed, and handle missing contacts explicitly. The supplied example is for one contact.

Why not simply turn the thermostat off?

Off behavior, frost protection and restart behavior depend on the equipment. This recipe leaves the operating mode alone and changes a supported target. It is not a universal replacement for the thermostat’s own window feature, and it does not promise to stop all heat.

Does this work without internet?

The automation logic runs in Home Assistant. Both the contact and thermostat integrations must also work locally for the complete routine to keep working during an internet outage. Home Assistant itself must remain running.

Start with one room and a household agreement about the normal target, lower target and manual controls. If you are planning a wider installation, Tara’s configured Home Assistant setup explains the setup and handoff path.