Home Assistant 2026.3+ shows custom integrations' own brand images from custom_components/<domain>/brand/. Add a radiator with a forecast curve (solid past, "now" marker, dashed prediction) as icon.png/icon@2x.png (256/512 px, transparent) plus dark-theme variants, so the integration is easy to spot in Devices & services. Older HA versions ignore the folder and show the generic placeholder; the integration is unaffected. scripts/make_brand_icons.py regenerates the images with Pillow from the test requirements; the package check verifies sizes and transparency. Listed under 0.2.3, which has not been deployed yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
6.3 KiB
Markdown
127 lines
6.3 KiB
Markdown
# Changelog
|
||
|
||
Engineering findings and test evidence behind each change are in [AUDIT.md](AUDIT.md).
|
||
|
||
## 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.
|