Repository navigation
Feat/add mpc algo - #9
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces an MPC-based controller path (“shadow” diagnostics plus an optional “production mode” override) to the Smart Fan Controller Home Assistant integration, along with new diagnostics, CSV logging fields, and supporting tests/docs.
Changes:
- Add
MPCShadowController(learned model + MPC-lite scoring) and integrate it into the control loop, optionally overriding the live rule-based fan decision in “production mode”. - Extend diagnostics/CSV logging with MPC shadow outputs (status, cost, confidence, predictions, disturbance bias) and add sensors for learned per-mode MPC profiles.
- Add tests covering MPC shadow behavior (including defrost/HVAC-idle pausing) and update translations/docs.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| custom_components/smart_fan_controller/mpc_shadow.py | Adds the MPC shadow/production controller implementation and diagnostics payload. |
| custom_components/smart_fan_controller/init.py | Wires MPC evaluation into the control loop and introduces production override logic. |
| custom_components/smart_fan_controller/switch.py | Adds a config switch to toggle MPC Production Mode. |
| custom_components/smart_fan_controller/sensor.py | Adds MPC shadow diagnostic sensors and MPC learned-profile sensors. |
| custom_components/smart_fan_controller/data_collection.py | Adds MPC shadow fields to CSV logging schema and recording. |
| custom_components/smart_fan_controller/const.py | Adds production-mode option constants and legacy entity-key migration mappings. |
| custom_components/smart_fan_controller/config_flow.py | Exposes MPC production mode in config/options UI. |
| tests/test_mpc_shadow.py | New test suite for MPC shadow diagnostics/guardrails and CSV columns. |
| tests/test_hvac_idle.py | Extends HVAC-idle coverage to include MPC shadow pause/decay behavior. |
| tests/test_data_collection.py | Updates expected CSV row layout for new MPC columns. |
| README.md | Updates docs to describe MPC controller + production mode switch. |
| docs/mpc_shadow_mode.md | Adds MPC shadow mode documentation (currently inconsistent with production mode). |
| custom_components/smart_fan_controller/translations/en.json | Adds translation strings for MPC production mode option. |
| custom_components/smart_fan_controller/translations/fr.json | Adds translation strings for MPC production mode option. |
| scripts/analyze_mpc_viability.py | Adds offline analysis script for comparing live vs MPC shadow behavior. |
Gamso
force-pushed
the
feat/add-mpc-algo
branch
2 times, most recently
from
April 6, 2026 08:45
56d7179 to
8773bbd
Compare
- Runs an MPCController in observation mode every control cycle (shadow learning) - Adds a production mode toggle switch; when enabled, the MPC decision replaces the rule-based heuristic for direct fan control - Shares the ThermalLearning backend with the heuristic controller; idle, defrost, and window-open periods are excluded from learning and MPC evaluation - Exposes 12 diagnostic sensors (status, reason, fan mode, cost, confidence, predicted temperatures at 10 and 30 min, dead time, known profiles, disturbance bias, match, would-change-now) - Adds CSV data-collection columns for offline MPC analysis - Entity migration mapping included so existing HA installations keep history
…pe service Learning data integrity: - Use median (not mean) for effective slope computation, resisting outlier contamination from VTherm EMA inertia after mode transitions - Add 30-minute learning cooldown after large setpoint drops (SETPOINT_DROP_LEARNING_COOLDOWN) to avoid recording stale slopes - Require fan mode to be active for ≥ 2× dead_time before accepting slope samples (MIN_ESTABLISHED_RATIO), ensuring the EMA has fully converged to the current mode's thermal response MPC monotone constraint: - Enforce slope(mode_i) ≤ slope(mode_i+1) via isotonic forward pass when all fan-mode profiles are learned; skip when profiles are partial - Prevents contaminated profiles from causing MPC to rank a weaker fan mode above a stronger one New service — set_effective_slope: - Manually override the effective slope for a specific fan mode / HVAC mode profile by replacing stored samples with synthetic ones - Useful for correcting contaminated profiles without full learning reset
Remove the rule-based heuristic controller (controller.py) and make MPCController the sole, always-active decision engine. Configuration cleanup: - Remove soft_error, hard_error, learning_enabled, mpc_production_enabled parameters (config flow, translations, options flow) - Remove production_mode and enabled toggles from MPCController - Remove step-down limit (_apply_step_down_limit); step-down hold remains - Empty the switch platform (no more user-facing switches) Sensor/data cleanup: - Remove MPC Match, Learned Soft Error, Learned Hard Error sensors - Remove mpc_match column from CSV data collection - Remove learning_enabled attribute from ThermalLearning; always on - Rename data_collection shadow parameter to mpc_decision Migration cleanup: - Remove LEGACY_OBJECT_KEY_MAP and extract_object_key_from_unique_id - Remove _async_migrate_entity_registry and entity registry import - Users upgrading from a legacy install start fresh Tests: - Delete test_entity_migration.py (migration removed) - Delete heuristic controller tests; replace with MPC-focused test suite - Rename all test_shadow_* functions to test_mpc_* - Remove production_mode, enabled, live_decision_fan from all test calls Documentation: - Clean README, docs/mpc_mode.md, copilot-instructions, and skill files of any reference to removed features or prior architecture
- route services to the correct config entry via climate_entity - prevent duplicate climate entries in config flows - apply learned settings to runtime options and reset auto-apply state on learning reset - scope sensor entity IDs by climate entity and migrate legacy IDs automatically - enrich CSV audit rows with live control-loop metrics - update tests, translations, and README for the new behavior
…guard, code smells
- Extract MPC cost function magic numbers into named module-level constants
(COMFORT_ERROR_WEIGHT, OVERSHOOT_QUADRATIC_WEIGHT, URGENCY_SENSITIVITY, etc.)
- Add fan_modes ordering validation: warn when learned slopes violate monotonicity
- Fix retry storm on fan command failure: update last_change_time even on error
to prevent rapid-fire retries when the climate API is broken
- Replace _services_registered flag with hass.services.has_service() for
race-free service registration across concurrent entry setups
- Fix data_collection rotated path using os.path.splitext() instead of
fragile str.replace('.csv', '_old.csv')
- Fix thermal_learning serialization key slope_M2 → slope_m2 for naming
consistency (with backward-compatible deserialization)
- Extract _should_collect_slope_sample() helper from nested learning gate
- Extract _update_sensors() helper to deduplicate sensor update loops
- Delete unused switch.py stub and remove Platform.SWITCH from PLATFORMS
- Add replay_bench.py to replay csv file.
Gamso
force-pushed
the
feat/add-mpc-algo
branch
from
April 14, 2026 18:40
b763fb5 to
8dda89c
Compare
- treat idle operating state as HVAC idle during disturbance detection - preserve sparse learned profiles and enforce monotone known slopes during partial learning - make replay bench snapshot-aware with time window filtering for real-trace analysis - add real trace datasets, regression tests, and reference analysis notes
Agent-Logs-Url: https://github.com/Gamso/smart_fan_controller/sessions/87b4ec4e-2fc0-4309-b6b8-ae03ea4b43b0 Co-authored-by: Gamso <13354981+Gamso@users.noreply.github.com>
fix: guard against None in data_collection projected_temperature round()
- Implement dynamic, adaptive simulation horizon length based on dead times to eliminate lag blindness - Decouple dead-time tracking separately for heat and cool modes with robust schema fallback migrations - Transition mode-ranking weights to physical non-linear power curves [1.0, 1.5, 3.0, 6.0] - Refactor comfort cost to calculate step-by-step urgency dynamically inside the simulation loop - Re-establish strict zero comfort cost within target deadbands
…loop abort The response_events list contains 3-tuples (timestamp, minutes, hvac_mode) since the hvac_mode field was added, but sensor.py was still unpacking them as 2-tuples (`for _, t in learning.response_events`), raising a ValueError. Because _update_sensors() calls sensor.async_write_ha_state() synchronously before _async_apply_fan_change(), this exception was propagating up through run_control_loop and aborting the cycle before any fan change could be applied. This caused the MPC-recommended mode (e.g. superhigh) to never be set on the climate entity, requiring manual intervention. - sensor.py: use item[1] indexing instead of 2-tuple unpacking - thermal_learning.py: remove unused `ts` variable in get_dead_time() - tests: add regression test covering mixed 2- and 3-tuple response_events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
docs/mpc_shadow_mode.mdto reflect MPC production mode behavior and correct entity IDsmpc_shadow_mode/mpc_shadow_enabledfromLEGACY_OBJECT_KEY_MAPinconst.pyto prevent unintended migration to production switch