Files
heating-mpc-ha/AGENTS.md
T
2026-10-26 17:34:32 +02:00

12 KiB

AGENTS.md — Heating MPC

Project mission

Build a local, configurable, testable Home Assistant custom integration for model-predictive heating control on Home Assistant OS (HAOS), Raspberry Pi 5. The home has multiple indoor temperature sensors, configurable comfort weights, outdoor weather sensors, one physical ON/OFF gas-boiler relay, and an existing Home Assistant generic_thermostat.

The project starts as a read-only observer. It learns thermal behavior and predicts possible heating decisions. Any future control of real heating equipment is a separate, explicitly authorized milestone.

Working agreement: Architecture, requirements and results are discussed in ChatGPT; source-code implementation, tests and commits happen in Codex in this repository. Treat the files and current code in this repository as the implementation source of truth, not verbal descriptions of earlier ZIP releases.

Starting point / status

  • Baseline: v0.2.1, experimental custom integration (custom_components/heating_mpc).
  • Native HA config and options flows; no Docker service, MQTT broker or direct InfluxDB connection needed.
  • Reads room sensors, an existing climate entity, the physical relay state and prioritized weather sources.
  • Uses 5-minute observations, per-room linear RC-like thermal models with a heating-lag approximation, persistent learned parameters, and an enumerative binary MPC optimizer.
  • Exposes status/diagnostics, a weighted temperature, selected outdoor temperature, per-room 60-minute prediction entities and a hypothetical proposed-heat binary sensor.
  • Weather variables other than outdoor temperature are currently for diagnostics/comparison only.
  • No backfill from Recorder; no hourly weather forecasts; no validated 60-minute out-of-sample accuracy; no actuator control.
  • Offline unit tests exist in tests/. Real HAOS integration and restart/unload behavior still need thorough testing.

Do not claim an item is implemented or validated solely because it is listed in ROADMAP.md. Check the code and tests first.

Non-negotiable safety rules

  1. Observation-only by default. The existing generic_thermostat is the sole controller of the physical boiler switch until the user explicitly approves a future control milestone. Never quietly add switch.turn_on, switch.turn_off, climate.set_temperature, climate.set_hvac_mode, climate.set_preset_mode, relay automations, or equivalent writes.
  2. Never connect binary_sensor.heating_mpc_proposed_heat directly to the relay. It is diagnostic output, not a certified control signal.
  3. One physical relay, one writer. Any future live implementation must provide a proven handover/arbiter design; generic_thermostat and MPC must never compete over the same actuator.
  4. Manual heat/off is authoritative. The user controls HVAC mode; do not automatically switch from off to heat, including after restart. Preserve user-selected Comfort/Away/Sleep targets (currently 22/19/21 °C) instead of resetting them.
  5. Fail safe. On missing/stale/implausible sensor data, optimizer failure, restarts, incomplete initialization or loss of connectivity: never issue an unvalidated heat request. For future live control, define and test safe fallback/recovery before enabling it. Fallback must not create two simultaneous writers.
  6. Protect the boiler. For future control, enforce minimum ON and OFF times, bounded setpoints, watchdog and recovery rules. Do not change gas/combustion settings, boiler flow temperature, firmware or wiring. The Immergas boiler is non-condensing, with conventional radiators; setting the boiler's flow temperature is outside this integration's scope.
  7. No experiments that heat the apartment without the user's opt-in. Avoid automatically generating artificial ON cycles to accelerate model training.
  8. Never introduce cloud dependencies, secrets in source control, or external network access for model inference. Default to local operation and HA entities.

Hardware and Home Assistant context

  • HA host: Raspberry Pi 5 with HAOS.
  • Heating: non-condensing Immergas Eolo Star (exact variant to be verified), aluminum radiators, copper plumbing, two-room apartment; relay is binary ON/OFF.
  • Existing thermostat platform: generic_thermostat; source temperature is a weighted indoor average. Existing Comfort/Away/Sleep targets: 22/19/21 °C; user manually selects heat/off.
  • Known example switch: switch.central_heating_switch. Known weighted average sensor: sensor.average_temperature. The exact climate entity ID must be verified; do not assume climate.thermostat.
  • Previously configured individual sensor examples (informational, not defaults):
    • sensor.living_universal_remote_temperature
    • sensor.hue_motion_sensor_1_temperature
    • sensor.air_purifier_temperature
    • sensor.bedroom_universal_remote_temperature
    • sensor.bathroom_temperature
  • Outdoor weather comes from existing HA sensors originally populated from OpenWeatherMap/InfluxDB. The user wants to swap and compare providers in the UI, not in code.
  • The weather series includes temperature, wind, clouds, humidity, feels-like, pressure, visibility, rain and snow. Sensor units, freshness and meanings must be checked before using them to train a model.

All example entity IDs are examples only. No user-specific ID, room count, provider, comfort target, weights or outdoor data source may be hard-coded.

Configurability contract

  • Use Config Flow + Options Flow for entity selection and tuning. Avoid requiring YAML edits for regular operations.
  • Allow selecting, removing and replacing indoor sensors (up to the current supported limit), plus independent positive comfort weights.
  • Every weather variable should accept an ordered list of HA sensor entity IDs. Select the first healthy, unit-compatible, plausible and eventually fresh source; expose the chosen source and alternatives in diagnostics.
  • Temperature must be available; other meteorological variables must be optional and cannot break the thermal controller if absent.
  • Support reconfiguration without corrupting learned models. Preserve compatible room histories; invalidate or migrate incompatible state explicitly and document why. When changing weather providers, beware of systematic sensor offsets.
  • A climate reference is read-only during shadow mode. Its requested target/preset/HVAC mode must remain owned by the existing thermostat/user.
  • Use translation keys for UI strings; maintain at least en and ro when changing exposed UI flows.
  • Entity unique IDs must remain stable across safe upgrades; handle removed/replaced sensors without leaving orphan entities.

Architecture boundaries

Keep separation between:

  1. HA integration layer: config entries, sensors, entity registry, event/update lifecycle, storage, read-only state acquisition.
  2. Data preparation: quality/staleness checks, unit normalization, sensor alignment and handling missing data.
  3. Thermal model: pure Python, independently testable learning/prediction algorithms for each room (eventually interactions between rooms).
  4. Optimization: pure Python, independently testable finite-horizon ON/OFF plan evaluation with actuator constraints.
  5. Evaluation/diagnostics: timestamps, input provenance, forecast trajectories, prediction errors and comparison to actual observed events.
  6. Optional future actuator layer: disabled/absent until separately designed, tested and explicitly approved by the user.

Favor the standard library and small dependencies. Heavy compute must not block Home Assistant's asyncio event loop. Use supported HA APIs and offload expensive optimization if needed. Avoid unnecessary polling, disk writes, excessive log volume and unbounded entity attributes.

Modeling rules

  • Current model form: dT_5m = a * (T_out - T_room) + b * effective_heat + c, with a smoothed heater-command proxy. Coefficients are estimates, not measured boiler efficiency.
  • A relay on is not proof that the gas burner is firing. Never treat ON duration as metered gas usage or claim fuel savings without gas-consumption evidence.
  • Track sample count and ON/OFF distribution. An in-sample 5-minute MAE is not validated 60-minute forecast accuracy.
  • Implement holdout / walk-forward testing for horizons of 15, 30, 60 and 120 minutes; compare to naive persistence and the existing thermostat.
  • Record the plan and the input snapshot that produced a prediction, then compare it to actual temperatures only under appropriate command/exogenous-input assumptions. Distinguish counterfactual MPC forecasts from forecasts of the actual generic_thermostat behavior.
  • Validate model identifiability, parameter stability, outlier rejection, missing observations, power outages, heater transitions within a sampling window, and multiple sensors in the same physical room.
  • Weather covariates beyond temperature should be added only if they improve held-out performance; avoid treating feels_like as physical outdoor air temperature. Forecast values and observed values must be distinguished.
  • One switch heats all rooms: optimization can trade off room comfort, but cannot independently heat a cold bathroom without influencing warmer rooms.

Repository conventions

Expected structure (adapt only through deliberate refactoring):

custom_components/heating_mpc/
  __init__.py
  manifest.json
  config_flow.py
  const.py
  coordinator.py
  physics.py
  weather_sources.py
  sensor.py
  binary_sensor.py
  strings.json
  translations/{en,ro}.json
hacs.json
tests/
README.md
AGENTS.md
ROADMAP.md
  • Keep pure model/optimizer logic importable and testable without Home Assistant installed.
  • Keep config migration and persisted-model schema backward compatible where possible; version persisted data explicitly when evolving its format.
  • Follow Home Assistant conventions for async config entry setup/unload/remove, entity lifecycle, options flows and translation validation.
  • Avoid speculative API usage. Verify Home Assistant behavior with a runnable test or documented supported API before depending on it.
  • Add tests with every behavior change; prioritize tests for lifecycle, reload, reconfiguration, persistence and fault handling.
  • Make small focused commits and record changes in a changelog or release notes. Never advance version numbers without corresponding tests/documentation.

Development workflow for Codex

  1. Inspect the repository first. Read README.md, ROADMAP.md, implementation and tests. Determine the actual current version/behavior.

  2. Audit baseline v0.2.1 before major features: confirm shadow-only semantics, config entry migration, sensor collection, update/reload, uninstall cleanup and persisted-state correctness. Identify and fix correctness/safety bugs first.

  3. For each task, state the scope, compatibility and safety implications. Keep modifications narrow; do not combine cleanup with an unauthorized live-controller implementation.

  4. Run at minimum:

    python -m unittest discover -s tests -v
    python -m compileall -q custom_components/heating_mpc
    

    Add more integration tests, lint/type checks and HA validation as tooling is introduced. Report exactly what was and wasn't run.

  5. Add/adjust tests for edge cases and migrations. Update README/ROADMAP and translations when the user-facing behavior changes.

  6. Summarize touched files, tests, known limitations and how the user can safely try the change on HAOS. Do not claim HAOS/device testing unless performed.

  7. No autonomous deployment to the real boiler. Installing code is not authorization to enable control mode.

Release acceptance rules

A release is not ready simply because unit tests pass. Require:

  • No regression in the existing Generic Thermostat or its presets/manual HVAC mode.
  • No unexpected service calls to heater/thermostat while in shadow mode.
  • Correct handling of unavailable, stale, nonnumeric and changing input sources.
  • Config/options flow, restart, reload, entity-registry cleanup, model persistence and uninstall verified.
  • Documented diagnostics and limitations; no unsupported fuel-savings promises.
  • For any future live control: a separate safety review, test evidence, opt-in UX, exclusive relay ownership, watchdog/fallback and explicit user approval.

See ROADMAP.md for ordered milestones. Prioritize correctness, reproducibility and user control over adding features quickly.