Night cooling purge that pulls in cool air only when it helps
On summer nights the bedroom window opens automatically only when outdoor air is at least 3 °C cooler than indoors and indoor CO₂ is above 900 ppm, closing at 05:30 or when outdoor temperature rises within 1.5 °C of indoor.
# HearthNodes recipe 12 - night cooling purge
alias: "Climate - bedroom night purge that earns its keep"
id: hn_climate_night_cooling
description: "Open 12 percent only when outdoor air helps and CO2 needs clearing"
mode: restart
max_exceeded: silent
trigger:
- platform: numeric_state
entity_id: sensor.outdoor_temperature
below: "{{ states('sensor.bedroom_temperature') | float(30) - 3 }}"
for: "00:05:00"
id: cooler_outside
- platform: numeric_state
entity_id: sensor.bedroom_co2
above: 1400
id: co2_spike
- platform: state
entity_id: binary_sensor.rain_detected
to: "on"
id: rain_started
variables:
gap_pct: 12
end_conditions:
- "05:30"
- "rain"
- "delta_t_below_1_5"
- "co2_below_700_for_20min"
condition:
- condition: time
after: "21:00:00"
before: "05:30:00"
- condition: state
entity_id: binary_sensor.bedroom_window_manual_override
state: "off"
- condition: numeric_state
entity_id: sensor.rain_accumulation_15min
below: 0.1
- condition: template
value_template: >-
{{ states('sensor.bedroom_co2') | int(0) > 900
or states('sensor.bedroom_temperature') | float(20) > 24 }}
action:
- choose:
- conditions:
- condition: trigger
id: rain_started
sequence:
- service: cover.set_cover_position
target:
entity_id: cover.bedroom_window_actuator
data:
position: 0
- conditions: []
sequence:
- service: cover.set_cover_position
target:
entity_id: cover.bedroom_window_actuator
data:
position: "{{ gap_pct }}"
- service: fan.turn_on
target:
entity_id: fan.bedroom_supply
data:
percentage: 30
- delay: "00:30:00"
- service: fan.turn_off
target:
entity_id: fan.bedroom_supply
- wait_for_trigger:
- platform: time
at: "05:30:00"
- platform: state
entity_id: binary_sensor.rain_detected
to: "on"
- platform: numeric_state
entity_id: sensor.bedroom_co2
below: 700
for: "00:20:00"
timeout: "08:00:00"
continue_on_timeout: true
- service: cover.set_cover_position
target:
entity_id: cover.bedroom_window_actuator
data:
position: 0
# A 12 cm gap on this casement gives about 34 m3/h. Rain sensor offline -> window
# held shut, MVHR boost instead. Actuator loss while open -> 15 minute watchdog
# cuts the actuator supply, which is the fail-safe direction for a window.
Trigger · numeric_state
sensor.outdoor_temperature
Outdoor temperature falls more than 3 °C below the bedroom temperature, between 21:00 and 05:30.
Step-by-step
- cover.bedroom_window_actuatorOpen the window to 12 % — a 12 cm gap at this window's geometry gives 34 m³/h at typical night breeze, enough to purge CO₂ without a draught across the bed.
set_cover_position · 12 - fan.bedroom_supplyRun the low-speed supply fan for 30 minutes to establish flow; it switches off on its own timer rather than on the window state.
turn_on · speed low · 30 min - cover.bedroom_window_actuatorClose on the first of four independent end conditions, each of which on its own means the purge has stopped helping.
set_cover_position · 0 on any of: 05:30, rain, ΔT < 1.5 °C, CO₂ < 700 ppm for 20 min
Open to 12 %, not fully
A fully open bedroom window at night creates a draught across the bed at exactly the temperature where people are least tolerant of it. Work out the gap that gives you 30–40 m³/h: for a typical 1.2 m casement that is about 12 cm. Measure it once and put the percentage in the recipe.
Gate on CO₂ as well as temperature
Temperature alone opens the window on a cool night with no ventilation need, which wastes heat and lets in noise. Requiring CO₂ above 900 ppm means the purge only happens when there is actually stale air to remove. In a two-person bedroom this triggers 8–10 times a month in summer.
Give it four independent ways to close
Time (05:30), rain, temperature convergence and CO₂ clearance. Each one alone is sufficient. An automated window with only one close condition is a window that stays open in a rainstorm sooner or later.
Hardware
| Model | Protocol | Link | Role in this chain |
|---|---|---|---|
| Chain window actuator (24 V) with a Matter module | matter |
wired | 24 V chain actuator, wired because a battery unit would need charging on exactly the nights it is needed. |
| Weather station with rain detection | zigbee |
wireless | Rain flag plus outdoor temperature from the same mast so the two readings are consistent. |
| CO₂ sensor with NDIR measurement | matter |
wired | NDIR, not eCO₂ from a VOC estimate; a bedroom purge decision based on estimated CO₂ will open the window when it should not. |
When it fails
If the rain sensor goes offline, the window is held closed and the recipe falls back to running the MVHR boost instead, which is less effective but cannot flood the room. If the actuator loses communication while open, a 15-minute watchdog closes it by cutting the actuator's supply, which is the fail-safe direction for a window.