Skip to content

TOU Pre-cool Before Peak on Hot Days — Design

Date: 2026-07-03 Status: Approved (deliberate reversal of the "Eco+ owns all HVAC" rule — see below)

Goal

On days when the forecast high exceeds 90 °F, have Home Assistant pre-cool all three Ecobees to a 70 °F cool setpoint starting 2 hours before the TOU peak period, then 1 minute before peak begins release the hold so the Ecobee's own Eco+ Time-of-Use logic resumes control through peak.

Deliberate rule reversal

This repo's standing rule (CLAUDE.md → Climate System; memory ecobee-owns-hvac) is "Eco+ TOU is the thermal management system — HA does not write HVAC setpoints; never build HA pre-cooling." The user has explicitly chosen to reverse that for this one sanctioned case (answered "Proceed + update docs"). CLAUDE.md and the memory are updated in the same change so a future session doesn't "fix" this by deleting it.

The tug-of-war risk the old rule warned about is mitigated by the guaranteed hand-back (the precool_active flag + a startup backstop, below): HA only ever holds the setpoint during the pre-peak window and always releases it before peak.

Timing (Dominion Schedule 1G)

  • Summer (months 5–9) weekday peak is a fixed 3–6 pm. 90 °+ highs only occur in summer.
  • Therefore: pre-cool at 13:00, resume at 14:59, gated to weekdays and summer months (5–9) so the fixed times always line up with the 3 pm summer peak. (A freak 90 ° winter day has a different peak schedule — 6–9 am / 5–8 pm — so the summer-month gate keeps the fixed times correct.)

Components

1a. Helper — input_boolean.precool_active

  • configuration.yaml, next to sleeping / good_night_error.
  • Name "Pre-cool Active", icon mdi:snowflake-thermometer.
  • No initial: → persists across restarts (restore_state). Default off.
  • On while an HA pre-cool hold is in effect; the resume automation keys off it.

1b. Helper — input_number.precool_high_threshold

  • configuration.yaml input_number: section.
  • Name "Pre-cool Forecast-High Threshold", icon mdi:thermometer-high, min 80 / max 110 / step 1, unit °F, mode: box.
  • No initial: so a dashboard tweak persists across the frequent CI config restarts (which initial: would reset). Consequence: on the first boot after deploy it reads the 80° min — set it to the design default 90 once (mirrors the garage_auto_open_* "set once after first deploy" convention).
  • The forecast-high trip point (°F): pre-cool runs when today's high exceeds it.

2. Automation A — "Climate — Pre-cool Before Peak (hot days)"

  • Trigger: time 13:00:00
  • Conditions (all):
  • weekday mon–fri
  • {{ now().month in [5,6,7,8,9] }} (summer)
  • numeric_state on sensor.weather_forecast_daily with above: input_number.precool_high_threshold — HA's numeric_state accepts an entity_id for above, so the trip point is read from the tunable helper (no automation edit needed to change it).
  • Actions:
  • climate.set_temperature on climate.bedroom, climate.office, climate.dining_roomtarget_temp_high: 70 (cool), target_temp_low: 65 (heat; keeps the ≥5 °F Ecobee deadband, won't run on a 90 ° day). Units stay in heat_cool. This creates the pre-cool hold.
  • input_boolean.turn_onprecool_active
  • mode: single

3. Automation B — "Climate — Resume Ecobee Control Before Peak"

  • Triggers:
  • time 14:59:00 (id peak_soon)
  • homeassistant start (id ha_start) — backstop if HA was down at 14:59
  • Conditions (all):
  • input_boolean.precool_active is on (only releases a hold we placed; always releases regardless of how the forecast changed 13:00→15:00)
  • {{ now().hour * 60 + now().minute >= 899 }} (≥ 14:59 — true for the time trigger; on startup only fires if we're already at/after 14:59, so a restart at 13:30 doesn't prematurely cancel a still-legitimate pre-cool)
  • Actions:
  • ecobee.resume_program resume_all: true on the three Ecobees — clears the HA hold and returns each to its programmed schedule with no manual hold, so Eco+ TOU runs freely (a lingering manual hold would suspend Eco+ adjustments). Chosen over set_preset_mode: home, which would itself be a comfort hold.
  • input_boolean.turn_offprecool_active
  • mode: single

Docs / tests updated in the same change

  • CLAUDE.md — Climate System (note the sanctioned HA-writes-setpoints exception), Architecture automation list, Key Entities (input_boolean.precool_active).
  • Memory ecobee-owns-hvac.md — amend to record the one exception + link.
  • docs/climate.md — user-facing description of the hot-day pre-cool.
  • docs/automations.md — technical per-automation reference entry.
  • tests/fixtures/entities_allow.txtinput_boolean.precool_active (forward ref until the next make snapshot).

Out of scope / non-goals

  • No dynamic "N hours before the next peak" computation — the fixed summer schedule makes 13:00/14:59 correct and matches how the TOU sensors already hardcode the hours.
  • No pre-cooling in winter, on weekends, or below a 90 ° forecast high.
  • No change to the §7 presence automations or Eco+ settings.