First part of Milestone 1: Forecast Error sensors scoring the thermal model against reality, forecast trajectories, Learning Progress and Last Sample sensors, rejected-sample and poll-outcome counters, plus lint and rollback-contract tests. README explains forecast accuracy, the 30-minute learning wait after a restart and where Developer Tools now lives. ROADMAP marks the items now backed by tests; AUDIT records the evaluation design and evidence. Still observation-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.4 KiB
Changelog
Engineering findings and test evidence behind each change are in AUDIT.md.
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),skilland 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) andplan_15min(the proposed ON/OFF plan), labelled counterfactual. - Status:
rejected_samplesper room inmodels,sample_results_since_startcounting how each poll was handled, andsample_result: waiting_for_inputswhen 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_Storefiles 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_roomsandweight_coverage(share of the total comfort weight covered by the rooms used), and a per-roomusedflag ininput_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_roomswhile 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_24hin 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, includingmax_age_seconds_24h),heat_lag,heat_lag_uncertainty,sample_result,retired_room_models, and per-room accepted ON/OFF counts inmodels. - Statuses
invalid_weightsandinputs_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_qualityandweather_comparisonare no longer written to the Recorder; they change every poll. Other attributes are still recorded.
Persisted data
- Model payload
schema_version2 (0.2.1 wrote no version). Optional keys: per-roomon_count/off_countandretired_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
helpertoservice. 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.