Files
buzeraandClaude Opus 5.5 2d027f367a
Tests / tests (requirements-test-latest.txt) (push) Successful in 1m22s
Tests / tests (requirements-test.txt) (push) Successful in 1m26s
Release 0.4.2
Final stability fixes after 0.4.1: Model Error leaves out spans with
unknown inputs; window sensors unknown at startup stay unknown, with last
known states restored as unknown across restarts; unload, reload and
removal can no longer publish stale results or recreate a deleted model;
Forecast Error scores only forecasts whose plan the relay matched within
2 minutes. Adds Reset learned model to Configure. Still observation-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 04:56:28 +02:00

19 KiB
Raw Permalink Blame History

ROADMAP.md — Heating MPC

Planning document, 2026-10-26. Architecture and scope are discussed in ChatGPT; implementation happens in Codex. Priorities may change based on data collected in Home Assistant. Check code/tests before marking an item complete.

Goal

Deliver a fully local Home Assistant custom integration for HAOS on Raspberry Pi 5. The integration learns how each room warms and cools, uses selectable indoor/outdoor sensors, forecasts temperatures and — only after validation and explicit opt-in — can safely control one existing ON/OFF boiler relay through an exclusive-control architecture.

Success means predictable comfort, understandable decisions, safe operation and maintainability. Lower gas consumption is a hypothesis to measure, not a promised result.

Current baseline — v0.2.1

Current release: 0.4.0 — Milestone 0 reliability work, part of Milestone 1 and the first part of Milestone 2 on top of this baseline; see CHANGELOG.md. The lists below describe 0.2.1.

Implemented (experimental):

  • Native Home Assistant integration with UI-based Config Flow and Options Flow.
  • Multiple room temperature sensors and independent room comfort weights.
  • Ranked, swappable HA weather sensor sources with normalization/fallback and diagnostics.
  • Read-only reference to existing Generic Thermostat and ON/OFF relay.
  • Per-room online linear thermal learner, 5-minute sampling and persistent parameters.
  • Simple radiator-heat-lag approximation and hypothetical finite-horizon binary MPC plan.
  • Integration shown as service (not helper); configuration entry deletion cleans up saved model data.
  • Status, weighted temperature, outside temperature, individual +60-minute forecast entities, and proposed-heat diagnostic binary sensor.
  • Baseline pure-Python tests.

Not yet implemented or validated:

  • End-to-end HAOS tests across restart, reconfiguration and deletion.
  • Backfill of indoor sensors and relay history from Home Assistant Recorder.
  • Proper held-out, multi-horizon forecast evaluation; plotted predictive trajectories.
  • Explicit sensor freshness policies and full degradation/recovery semantics.
  • Weather forecast inputs, learned effects from wind/clouds or sunshine.
  • Identification of inter-room heat transfer and radiator dynamics beyond the present proxy.
  • Real boiler-burner detection or direct gas-use measurement.
  • Any live actuation (intentionally excluded from v0.2.1).

Current behavior: shadow mode only. generic_thermostat remains the one and only controller of the physical switch.

Milestone 0 — Audit and reliability (v0.2.x) — FIRST

Objective: Make the existing observer trustworthy before extending it.

  • Perform a source audit of v0.2.1: pure model, optimizer, config/options, coordinator update timing, persistent model and entity lifecycle.
  • Add Home Assistant test harness coverage for initial setup, update, restart/reload, options changes, missing sensors, heat/off, target changes, teardown and uninstall.
  • Verify that zero physical-device service calls occur in observation mode, including restart and failed update cases. (0.2.2: service-call guard on every HA Core test, including cold start with a stored model and optimizer failure, plus a static source check. Not yet observed on HAOS.)
  • Establish deterministic handling of 5-minute transitions, polling jitter, timestamp discontinuities, missing data and real switch transitions between samples. (0.2.2: relay changes timestamped by a read-only listener; offline and HA Core tests. Sensor alignment remains open.)
  • Add input freshness thresholds and diagnostics that identify exactly which source is missing/stale/invalid.
  • Verify that source switching, entity renaming, adding/removing rooms and replacing the relay do not silently reuse incompatible fitted coefficients. (0.2.2: tests for outdoor-source switching, adding, removing and re-adding rooms, and relay replacement. A renamed sensor is handled as removing one room and adding another; its old model is retained under the old ID.)
  • Version persisted model schema; test corrupted/older state and migration/rollback behavior.
  • Verify calculated sample totals and successful/failed fitting counters; expose reasons why training/prediction is unavailable. (0.3.0: per-room accepted/ON/OFF/rejected counts, per-outcome poll counters, Learning Progress and Last Sample sensors, Status reasons; covered by tests.)
  • Add CI, linting, tests and packaging validation (including HACS metadata/translations).
  • Update installation/release documentation and remove packaged __pycache__/.pyc files if present. (0.2.2: CHANGELOG with upgrade/rollback notes; package check rejects tracked bytecode.)

Exit criteria: No control writes; reproducible tests covering HA lifecycle; clean upgrade/removal; clear status during outages; no significant model-data loss or silent corruption on restart.

Audit update — 2026-10-26

See AUDIT.md. The source audit and focused repairs are complete; Milestone 0 acceptance is not complete. Offline boundary doubles cover setup, reload/unload, migration, removal, corrupt storage, missing inputs and manual off. A follow-up now adds 14 real HA Core 2025.12.0 tests on Python 3.13, including config/options flows, scheduling, registry cleanup and Store API calls. Disk I/O and source entities are mocked; HAOS and full-process restart tests remain open. Per-room accepted ON/OFF counts, additive payload schema v2, conservative relay-transition rejection, jitter normalization, Fahrenheit targets and forecast input-change guards are implemented.

Configurable room/weather report-age limits and per-source quality diagnostics are now implemented with offline coverage. Sensor alignment remains open. The HA Core harness and Forgejo/Gitea workflow are now added and pass locally; remote runner execution remains unverified. Next improve event-based sampling and identity/persistence migration tests, then extend the HA version matrix. Only after those reliability checks proceed to Milestone 1's recorded forecasts and walk-forward evaluation. Live control remains unauthorized.

A second audit pass (see AUDIT.md) fixed radiator-lag resets at every relay change, RLS covariance windup and a restore tolerance that could reset long-running models, optional weather sources that could not be cleared in Options, and spurious prediction discards. It added sample_result/lag diagnostics and a static shadow-only tripwire test. Relay transitions between polls are now integrated at their timestamp; multiple changes within one poll still need event-based relay history before the transition item below can be checked.

Release 0.2.2 adds that event-based relay history (read-only listener), keeps models of rooms removed in Options, shows each sensor's longest report gap, stops recording volatile attributes, and tests against HA 2025.12.0 and 2026.2.3.

Stabilization after 0.4.0 — 2026-10-27

See AUDIT.md. Four confirmed problems fixed, each with regression tests: unknown window states read as closed; learned coefficients reused after incompatible configuration changes (now per-component fingerprints with selective recalibration, logged in model_changes); plans published from inputs that changed during optimization or by an overtaken run; and model accuracy reported as if it were forecast accuracy. Reload/unload tests now cover repeated reloads (one relay listener, one polling coordinator). Released as 0.4.1; not yet tested on HAOS.

Final stability fixes after 0.4.1 — 2026-10-27

An independent review of 0.4.1 reported four problems; three were reproduced and the fourth (lifecycle races) confirmed by reading Home Assistant's unload order. Fixed with regression tests (see AUDIT.md): Model Error spans with unknown inputs are now incomplete, not scored; window sensors unavailable at startup are unknown, with last known states saved and restored as unknown; unload, reload and removal can no longer publish stale results or recreate a deleted model; Forecast Error scores only forecasts whose plan the relay matched within 2 minutes. Also added: Reset learned model in Configure. Released as 0.4.2; not yet tested on HAOS.

Milestone 1 — Explainable forecasts and dashboards (target v0.3.0)

Objective: Users can verify what the model predicts and whether it is actually accurate.

  • Expose trajectories for each room at 5–15-minute resolution for 2–3 hours, with forecast generation timestamp, horizon and input provenance. (0.3.0: 15-minute trajectory over the horizon; generation timestamp and provenance still to add.)
  • Expose predicted +15/+30/+60/+120 minute temperatures and full proposed ON/OFF schedule. (0.3.0: forecast_15min and plan_15min on each room forecast entity.)
  • Provide an HA dashboard example using native cards or a clearly documented optional chart card (do not bundle a heavyweight frontend unnecessarily).
  • Make clear that the MPC plan forecast is counterfactual while Generic Thermostat is controlling the relay; add a separate actual-policy forecast/evaluation pathway. (0.3.0: plan forecasts labelled counterfactual; evaluation uses the actual relay history. Stabilization: published forecasts are scored only when the relay followed their plan and otherwise counted as counterfactual. An actual-policy forecast, simulating Generic Thermostat, is still open.)
  • Store a bounded history of predictions with snapshots of inputs, proposed plan and eventually observed outcome. (Stabilization: each published forecast is kept with its start readings, plan, model revision and assumptions, including any it had to assume, until scored, in memory only; the scored statistics persist, split into matched, approximate, counterfactual and incomplete. No browsable history yet.)
  • Implement out-of-sample/walk-forward MAE and bias at 15, 30, 60 and 120 minutes; include sample counts and confidence/quality labels. (0.3.0: replay with parameters frozen at the forecast start and the actual relay history; skill against persistence. Stabilization: these are now the Model Error sensors, with RMSE, effective sample counts and quality labels; a separate Forecast Error sensor scores published forecasts. No confidence intervals yet.)
  • Compare against simple benchmarks such as current-temperature persistence and a fixed thermal baseline. (0.3.0: persistence done; fixed baseline open.)
  • Add inspectable explanations: expected heat loss, expected heating response, target, room weights and reason for the next proposed action.

Candidate quality gate: Sustain about 0.3–0.4°C or better 60-minute MAE on representative held-out data under comparable known relay input sequences, without systematic room bias. This is a starting engineering goal to validate, not a guarantee or an arbitrary gate to waive. Compare to baselines.

Milestone 2 — Better thermal identification (target v0.4.0)

Objective: Improve forecasts with genuinely useful features, not just more inputs.

  • Compare existing per-room linear model with a multi-zone RC model including inter-room heat exchange. (0.4.0: layered zone model with neighbour exchange; base model scored alongside on every forecast. Exchange between zones sharing one boiler is weakly identifiable and reported as such.)
  • Address multiple sensors within a single physical room; configurable room grouping, aggregation and comfort priorities. (0.4.0: zones with sensor weights, comfort weights and target offsets.)
  • Distinguish air/room thermal mass and radiator lag where observable; avoid overfitting unidentifiable parameters.
  • Add optional Recorder history import/backfill for indoor sensor + physical relay history; do not assume old HA Recorder data still exists.
  • Add outdoor forecast data with future timestamps (forecast provider selectable) and compare forecast-based versus constant-outdoor assumptions.
  • Experiment with wind/cloud cover as optional covariates; retain them only if held-out forecast error improves. Solar gains may require orientation/irradiance or a useful proxy. (0.4.0: wind speed, direction and gusts for open windows, optional and judged by improvement_vs_base; clouds and solar still open.)
  • Expose source reliability and provider comparison: normalized units, update age, outages and sensor offsets.
  • Handle shifts in room usage, opened windows, sensor relocation and season changes without unstable feedback. (0.4.0: opened windows handled by a separate ventilation layer; electrical loads by heat sources. Sensor relocation and seasons still open.)
  • Benchmark RAM, CPU and event-loop latency on Raspberry Pi 5. Prefer standard-library/small scientific dependencies and avoid heavy inference runtimes.

Exit criteria: Model complexity justified by reproducible forecast improvements over v0.3.0; stable fitting and manageable HAOS resource usage. Retain the simpler model as fallback where it performs better.

Milestone 3 — Safety design for optional control (target v0.5.0; NOT AUTHORIZED YET)

Objective: Design, simulate and review live actuation before any real actuator writes are enabled.

  • Specify a formal single-owner strategy for switch.central_heating_switch: no simultaneous Generic Thermostat and MPC writers.
  • Design explicit user-selectable controller modes: Observe (default), Advisory, MPC Active (separate opt-in), Fallback/manual.
  • Make manual off authoritative; never auto-enable heat. Preserve targets/presets (Comfort 22°C / Away 19°C / Sleep 21°C in current household; all configurable).
  • Define watchdog, heartbeat, max-command age, minimum ON/OFF time, bounds, restart rules and an unambiguous safe behavior on invalid data.
  • Test handover to/from Generic Thermostat with no overlap, stuck state, or unexpected ON request. Handover itself must be user-visible and reversible.
  • Add pure simulation / hardware-in-the-loop-style tests for sensor dropouts, rapid changes, relay availability, HA restart, config reload and network loss.
  • Perform dry-run comparison of live decisions versus the existing thermostat using recorded traces.
  • Provide a rollback playbook and explicit separate approval step to begin live experiments.

Hard gate: Do not add, enable or invoke real actuation merely because this milestone is on the roadmap. Get explicit user approval after the safety design and tests are reviewed. This includes indirect actuations via automations.

Milestone 4 — Controlled evaluation (future v0.6.x)

Only after the Milestone 3 gate has been satisfied:

  • Conduct short, supervised and reversible trials with one active controller at a time.
  • Compare comfort: time outside user-defined comfort band, degree-minutes of discomfort, overshoot and temperature variability per room.
  • Compare actuator commands: total commanded ON time, restart count and cycle lengths.
  • Where available, compare measured burner operation and gas-meter data normalized for outdoor weather. Relay ON time alone is not gas consumption.
  • Measure manual overrides, watchdog/fallback activations and recovery behavior.
  • Define clear criteria to return to the existing Generic Thermostat if predicted performance or safety degrades.

Milestone 5 — Stable release / HACS (future v1.0.0)

  • Document user-facing installation, config, sensor selection, tuning, compatibility, backup and uninstall.
  • Provide robust migration from old config entries and stored model data.
  • Stable entity IDs, diagnostics downloads where safe, translations and troubleshooting.
  • CI, meaningful automated HA integration tests and supported HA version policy.
  • Clean HACS repository metadata, release tags and changelog.
  • Clearly document the difference between a thermostat demand command and burner/gas consumption.
  • Publish only after real HAOS testing and acceptance criteria are met.

Non-goals (unless separately approved)

  • Replacing the boiler or modifying gas-side operation, burner modulation, flow-temperature electronics, wiring or safety circuitry.
  • Adding cloud AI/LLMs for thermostat decisions.
  • Creating a direct InfluxDB integration: weather data already exists as Home Assistant sensors.
  • Controlling individual radiators without individually addressable actuators.
  • Guaranteeing a fuel saving based solely on relay-state history.
  • Auto-switching the user's HVAC mode between off and heat.

Priority backlog for the next session

Items 1–3 of the original backlog are done (see AUDIT.md and CHANGELOG.md 0.2.2).

  1. HAOS acceptance of 0.2.3 by the user: install, restart, options reload, room removal and re-adding, manual heat/off, a stale and an unavailable room sensor (with the keep-last-value checkbox off and on), uninstall on a disposable entry; confirm Generic Thermostat behavior is unchanged.
  2. Finish Milestone 0: committed rollback/migration fixtures; failed-fit counters; lint/type checks; remote CI run. Stale-room policy decided in 0.2.3 (leave the room out, or optionally keep its last value for up to 24 hours). Before live control, decide a minimum weight_coverage and the outdoor-temperature outage policy, which still pauses.
  3. Configure zones, the UPS heat source and the windows on HAOS; after a week of heating review Model Error improvement_vs_base and quality, per-zone bias, coefficient confidence (base layer included), model_changes after any reconfiguration, and the Forecast Error counts (matched, approximate, counterfactual, incomplete and why). Switch off optional terms that do not help. During HAOS acceptance also try: a window sensor unavailable across an HA restart, a zone edit, a reload while the integration is running, Reset learned model and removing a disposable entry (its .storage/heating_mpc.<entry_id> file must be gone afterwards).
  4. Milestone 1 (rest): a dashboard example; forecast timestamps/provenance; explanations for the proposed action; an actual-policy forecast that simulates Generic Thermostat.
  5. Milestone 2 (rest): learned response times (compare candidate time constants out of sample), a wall-mass state if recovery data shows it is needed, Recorder backfill, weather forecasts, and a Raspberry Pi 5 resource benchmark.
  6. Only then consider the live-control design; do not implement live control without separate authorization.

Definition of done for each milestone

  • Documented requirements and behaviors, backward-compatibility notes and any schema changes.
  • Tests for nominal, edge and failure paths, with actual commands/results stated in the PR/commit summary.
  • No regressions to sensor configurability, preset behavior or manual mode control.
  • Observability sufficient to explain predictions and diagnose invalid inputs.
  • HAOS verification clearly differentiated from unit tests; no unsupported performance claims.
  • Release notes and installation/rollback instructions updated when appropriate.

Guiding principle: a reliable, locally explainable thermostat model is more valuable than a sophisticated optimizer whose predictions cannot be validated or whose failure behavior is unclear.