Skip to content

fix(predheat): allow temperature forecasts without heating-energy history - #5867

Open
liambresnahan wants to merge 4 commits into
springfall2008:mainfrom
liambresnahan:fix/predheat-optional-energy-history
Open

liambresnahan wants to merge 4 commits into
springfall2008:mainfrom
liambresnahan:fix/predheat-optional-energy-history

Conversation

@liambresnahan

@liambresnahan liambresnahan commented Oct 30, 2026 •

Copy link
Copy Markdown

Summary

Predheat currently includes the age of heating_energy history when calculating minute_data_age, even when no heating-energy entity is configured or it has no data. minute_data_entity() returns ({}, 0) in that case, so the minimum age is always zero. As a result, get_historical() ignores otherwise valid indoor/outdoor temperature and thermostat setpoint history and the forecast falls back to the 20°C default target.

This change makes heating-energy history optional for that age calculation:

  • Always consider outdoor, indoor and target-temperature history.
  • Only include energy-history age if energy history contains data.
  • Preserve the existing minimum-age behaviour where energy history is available.

Includes a focused regression test covering missing energy, shorter energy history, and missing target history, registered in the existing Predbat test runner.

Testing

  • Regression test added: predheat_optional_energy_history in apps/predbat/tests/test_predheat.py.
  • Verified the fork branch diff against upstream main: only apps/predbat/predheat.py, apps/predbat/tests/test_predheat.py and apps/predbat/unit_test.py changed.
  • Not run: coverage/run_all --test predheat_optional_energy_history, red/green reproduction, and coverage/run_pre_commit. The current environment cannot clone the repository or execute its test harness. Please treat CI and the regression test as pending, not passed.

Notes

@liambresnahan
liambresnahan marked this pull request as ready for review October 30, 2026 15:00
@github-actions github-actions Bot added the BOT_REVIEW Trigger an autotriage label Oct 30, 2026

@springfall2008 springfall2008 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated comment from the triage bot.

Reviewed at a5a2e92. The fix is correct: minute_data_age's only consumer is get_historical() (apps/predbat/predheat.py:276), the new history_ages list always has the three temperature entries so min() cannot go empty, and the truthiness of self.heating_energy is the right emptiness test — minute_data_entity() returns ({}, 0) only when the entity is unconfigured or its history yields no points, in which case the age carries no span information the replay could use. This resolves the second bug recorded from the #5153 review in tools/debug-journal.md (heating_energy unset pins minute_data_age to 0, so get_historical() always returns its 20.0 default), and the code now matches docs/predheat.md:103, which already says heating_energy can be commented out. By reading the new test against main's line: min() includes the 0 from the energy stub, minute_data_age becomes 0, use_days becomes 0, total_weight stays 0 and the 20.0 default is returned — both assertions fire, so the test is genuinely red/green against the fix. heat_energy_today/today_cost/run_simulation all degrade safely on the empty dict (0 so far today, early return, 0 cost). Registry entry added in unit_test.py ✓.

1 low finding posted inline. Notes, not findings: (a) the energy-present-but-short case is preserved as the body promises — an energy entity only hours old still floors the replay to 0 (age.days), but that self-heals as recorder history accumulates, unlike the unconfigured case this PR fixes; per-series ages inside get_historical() would be the deeper generalisation if that variant starts reporting, and the prune-blip path into the same 20.0 fallback is already recorded as #5456. (b) With the fix, schedule replay now actually runs in energy-less setups, so the pre-existing span-alignment behaviour of get_from_history() (missing minutes read as 0) becomes reachable there too; minute_data_age already caps the replay to each run's dense span, and the residual exposure is the same #5456 prune-blip entrance, unchanged by this PR.

Comment thread apps/predbat/tests/test_predheat.py Resolved
@springfall2008 springfall2008 removed the BOT_REVIEW Trigger an autotriage label Oct 30, 2026
@liambresnahan

Copy link
Copy Markdown
Author

Docstring issue resolved

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants