Files
heating-mpc-ha/CHANGELOG.md
T
buzeraandClaude Opus 5.5 17dbe76223
Tests / tests (requirements-test-latest.txt) (push) Successful in 1m45s
Tests / tests (requirements-test.txt) (push) Successful in 1m42s
Release 0.4.0
Zones, electrical heat sources, windows with ventilation, wind exposure
and recovery, and exchange between adjacent zones, all observational.
docs/MODEL.md documents the equations, units, coefficient meanings,
priors and bounds, learning conditions, forecast assumptions, validation
method and results, and limitations. README gains a configuration guide
for zones, heat sources and windows, the new diagnostics and the
accuracy comparison against the base model. CHANGELOG has upgrade notes
(config entry version 3, rollback needs the backup, renamed Status
attributes). ROADMAP marks the Milestone 2 items now covered; AUDIT
records the design decisions and evidence. AGENTS.md lists the new
modules and the convention that new model terms start at zero and must
beat the base model out of sample before being relied on.

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

244 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
Engineering findings and test evidence behind each change are in [AUDIT.md](AUDIT.md).
## 0.4.0 — 2026-10-27
Thermal zones, electrical heat sources, windows with ventilation and wind, and
heat exchange between zones (Milestone 2, first part). Still **observation-only**:
no new service calls, the boiler and thermostat are untouched. Tested in the Home
Assistant Core harness with HA 2025.12.0 and 2026.2.3; not yet on HAOS.
### Upgrade notes
- **Back up Home Assistant first.** The config entry moves to version 3: each room
sensor becomes a one-sensor **zone** with its comfort weight, and the sensor's
entity ID stays the zone's key, so learned models, forecast entities and
accuracy statistics carry over unchanged. No model reset is needed.
- **Downgrading needs the backup.** Older versions refuse a version 3 entry.
- Configure no longer asks for room sensors or weights; manage zones with **Add
zone** and each zone's edit button on the integration page.
- Status attributes renamed: `input_quality.rooms` → `input_quality.zones` (each
zone lists its sensors), `excluded_rooms` → `excluded_zones`,
`retired_room_models` → `retired_zone_models`. The Forecast Error attribute
`rooms` is now `zones`, keyed by zone name. The `invalid_weights` status is gone
(invalid stored weights fall back to 1.0). Update templates that used these.
- New layers start with no assumed effect and need data: the electrical term needs
gaming sessions (or other load changes), the ventilation terms need window
openings. Watch `improvement_vs_base` on the Forecast Error sensors before
relying on them; switch off optional terms that do not help.
### Added
- **Zones** (config subentries): name, several sensors with sensor weights, comfort
weight, target offset and adjacent zones. Sensor and comfort weights never change
learned thermal coefficients.
- **Heat sources**: active power (W/kW; VA and % rejected), zone, heat fraction,
automatic 24-hour baseline or manual value, "included in" another source (no
double counting), thermal response time, enable/disable.
- **Windows**: contact sensor (optional inverted polarity; unknown stays unknown),
zone, facing direction (default 345°), opening factor, enable/disable; a bounded
log of ventilation events.
- **Wind direction** and **wind gust** weather sources with priorities and fallback;
knots and ft/s accepted.
- Model options: electrical-heat forecast half-life, assumed open-window time,
recovery time constant, and wind / gust / cross-ventilation terms.
- Per-zone diagnostics on each zone's forecast entity: current temperature,
+15/+30/+60/+120-minute forecast, contributions in °C/h, coefficients with
confidence; Status lists heat sources, windows, ventilation and recent events.
- Forecast Error sensors: `base_model_mae` and `improvement_vs_base`.
- Poll outcomes `sensors_changed` and `ventilation`, with English and Romanian names.
### Changed
- Each zone's model is layered: the unchanged base model (fallback and
comparison), an extended layer with electrical heat and neighbours, and a
separate ventilation layer. Zones with an open, unknown or recovering window are
kept out of base and extended learning.
- Forecasts simulate all zones together, with electrical heat fading to baseline
and open windows closing after the configured time; the plan search uses an exact
compiled step and stays fast at 180 minutes.
- Accuracy scoring replays all zones with the actual relay, electrical heat and
window history, and scores the base model on the same spans.
### Persisted data
- Model payload `schema_version` stays 2 with optional new keys: `zone_models`,
`ventilation_models`, `heat_sources` (baseline samples) and `ventilation`
(events). Forecast statistics gain a base-model column; 0.3 statistics load.
### Development
- New pure modules: `learning.py` (named-feature RLS), `zones.py`, `heat_sources.py`,
`windows.py`, `zone_model.py`; [docs/MODEL.md](docs/MODEL.md) documents the model.
- Synthetic-apartment tests for gaming heat, ventilation with wind and recovery,
and coupled rooms, each checking recovered coefficients and out-of-sample
improvement over the base model.
## 0.3.0 — 2026-10-26
First part of Milestone 1: the integration now measures how accurate its thermal
model is. Still **observation-only**; no new options. Upgrading from an earlier
version: also read the notes of each version in between.
### Added
- Four sensors, **Heating MPC Forecast Error 15/30/60/120 min**: the thermal
model's mean absolute error over the last 7 days, scored out of sample against
what actually happened, using the relay's real ON/OFF history. Attributes show
the bias, the error of a no-change forecast (`persistence_mae`), `skill` and
per-room details. See README, "Forecast accuracy".
- **Heating MPC Learning Progress** (% towards forecasts being used) and **Heating
MPC Last Sample** (what the last poll did for learning, with English and Romanian
state names), so learning activity is visible without opening attributes.
- Room forecast entities: `forecast_15min` (temperature every 15 minutes over the
horizon) and `plan_15min` (the proposed ON/OFF plan), labelled counterfactual.
- Status: `rejected_samples` per room in `models`, `sample_results_since_start`
counting how each poll was handled, and `sample_result: waiting_for_inputs` when
the relay, thermostat, outdoor temperature or every room is missing.
### Changed
- The model is saved after each poll's forecasts are scored, with the forecast
statistics (about 8 KB for five rooms, at most 18 KB).
### Upgrade notes
- Six new entities appear (four forecast-error sensors, learning progress, last
sample). The error sensors stay unknown until forecasts can be scored: 15 minutes after
start for the 15-minute sensor, 2 hours for the 120-minute one. Early numbers
include the learning phase and are pessimistic.
- Rollback to 0.2.x is safe: older versions ignore the new saved keys, and the six
new sensors become unavailable (remove them in the entity settings if you roll back
permanently).
### Development
- Bug-finding lint (ruff: pyflakes, bugbear) in the checks and CI.
- Tests for restoring a model saved by 0.2.1 and for 0.2.1 being able to read
today's saved model.
- `.DS_Store` files are ignored and rejected by the package check.
## 0.2.3 — 2026-10-26
A stale or failed room sensor no longer pauses the whole integration. Still
**observation-only**. Upgrading from 0.2.1 (0.2.2 was not deployed): follow the
0.2.2 upgrade notes below as well.
### Changed
- A room sensor that is stale, unavailable, missing or invalid is now **left out**
instead of pausing everything: the weighted temperature, learning and forecasts
continue with the other rooms, whose comfort weights are re-normalized. Learning
and forecasts pause only if no room is usable, or if the relay, thermostat or
outdoor temperature is missing. Readiness considers only the rooms used.
### Added
- Checkbox **Keep using the last value of a room sensor that stopped reporting**
(setup and Configure, default off), for sensors that report only when the value
changes. A stale sensor's last value is then still used, for up to 24 hours
without a report. Unavailable or invalid sensors are always left out.
- Status attributes `excluded_rooms` and `weight_coverage` (share of the total
comfort weight covered by the rooms used), and a per-room `used` flag in
`input_quality`.
- Integration icon (a radiator with a forecast curve) in **Settings → Devices &
services**, with a dark-theme variant. Needs Home Assistant 2026.3 or newer;
older versions show the generic placeholder.
### Upgrade notes
- The new checkbox appears in **Configure**; existing installations start with it
off. If a room is often listed in `excluded_rooms` while its temperature is
steady, either raise that room's report-age limit or turn the checkbox on.
- Rollback to 0.2.2 or 0.2.1 is safe; older versions ignore the new setting.
## 0.2.2 — 2026-10-26 (not deployed)
Reliability release (Milestone 0). Still **observation-only**: the integration never
calls the relay, the thermostat or any other service. No new options or UI text;
entity IDs and settings carry over. Tested in a Home Assistant Core test harness
with HA 2025.12.0 and 2026.2.3; not yet tested on HAOS or with real devices.
### Upgrade notes
- Back up Home Assistant, replace `custom_components/heating_mpc`, restart Core.
- Saved models load, but coefficients learned by 0.2.1 were fitted with a broken
radiator-lag estimate (see Fixed). Either let them re-converge over a few days of
heating, or reset the model: disable the integration, delete
`/config/.storage/heating_mpc.<entry_id>`, restart Core, enable it again. Deleting
the file while the integration runs does not work; it saves the model again.
Deleting and re-adding the integration also resets it, but loses the settings.
- After each HA restart, learning pauses for about 30 minutes
(`sample_result: lag_uncertain`) because the radiator state is unknown.
Forecasts continue.
- After a day of running, compare each sensor's `max_age_seconds_24h` in Status
with the freshness limits in Configure (see README, "Choosing freshness limits").
- Rollback: restore the previous folder (or the backup) and restart. 0.2.1 reads
models saved by 0.2.2 and ignores the new keys.
### Fixed
- The radiator-lag estimate jumped to fully hot or fully cold at every relay
change. In simulation this learned the heating gain about a third too low, and
forecasts made just after a boiler cycle started from the wrong state.
- The learner's covariance grew without limit during long OFF periods (for
example a summer), which could destabilize learning when heating resumed and
eventually make a restart discard the saved model.
- Optional weather sources could not be removed in Configure.
- A finished forecast was discarded, making proposed heat unavailable for five
minutes, when only a diagnostic weather sensor or the thermostat's current
temperature changed during the calculation.
- Config entries from 0.1 were not migrated.
- Forecast entities of removed rooms stayed in the entity registry.
- Malformed or physically implausible saved models could crash setup or be used.
- ON/OFF readiness counts included rejected samples and other rooms' history.
- Polls 4–7 minutes apart, or containing a relay change, were learned as normal
5-minute samples.
- Thermostat targets were read as Celsius on Fahrenheit installations.
- Invalid room weights or optimizer settings could cause crashes.
- 30/45-minute horizons reported their end point as a 60-minute forecast.
### Added
- Room and weather report-age limits in setup and Configure (5–1440 minutes,
defaults 30 and 120). Stale outdoor sources fall back to the next one; a stale
room pauses learning and forecasts until it reports again.
- A read-only listener on the relay, so all relay changes between polls are
timestamped and integrated.
- Models of rooms removed in Configure are kept (up to 24) and restored if the
room is added back.
- Status attributes: `input_quality` (per-source state and report age, including
`max_age_seconds_24h`), `heat_lag`, `heat_lag_uncertainty`, `sample_result`,
`retired_room_models`, and per-room accepted ON/OFF counts in `models`.
- Statuses `invalid_weights` and `inputs_changed`.
### Changed
- Readiness now also requires 30 accepted ON and 30 accepted OFF samples per room.
- Learning skips intervals with a relay change, an outdoor-source switch or an
uncertain lag estimate, and polls not 270–330 seconds apart.
- `input_quality` and `weather_comparison` are no longer written to the Recorder;
they change every poll. Other attributes are still recorded.
### Persisted data
- Model payload `schema_version` 2 (0.2.1 wrote no version). Optional keys:
per-room `on_count`/`off_count` and `retired_learners`. Older readers ignore them.
### Development
- Home Assistant Core test harness for HA 2025.12.0 and 2026.2.3, a Gitea Actions
matrix over both, package and translation validation, and a static test that
fails if actuator service calls are added.
## 0.2.1
- Corrects the manifest classification from `helper` to `service`. Existing config
entries move from Helpers to **Settings → Devices & services → Integrations**
after replacing the files and restarting Home Assistant Core.
- Deleting the config entry removes its entities and the learned model
(`.storage/heating_mpc.<entry_id>`). The component folder stays until removed
manually.
- MPC behavior otherwise unchanged; read-only / shadow-only.