Conversation
automatic_config() pointed load_today, pv_today, import_today and
export_today at the first bound inverter's serial-named entities
(sensor.predbat_gateway_<suffix>_load_today, ...). Load and PV history are
fetched by entity id, so any change of the bound serial - an inverter
replacement, or a re-discovery that picks a different control target -
started history from zero and left the load forecast and PV calibration
with no days to work from.
Publish site-level counters without a serial -
sensor.predbat_gateway_{pv,import,export,load}_today - and bind the four
args to them. automatic_config() records the slot 0 inverter as the
source, so the values are the ones the plan already used. They are
published on each telemetry that includes the source inverter, and once
during auto-config so they exist before PredBat's first fetch. The
per-inverter counters are still published, from the same helper.
Existing gateway installs start these four histories again once under the
new entity ids.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
History is fetched by entity id, so pointing an arg such as load_today or pv_today at a new entity id restarts its history from zero, and the load forecast, PV calibration and ML load model then work from no days at all. Add PredBat.set_history_alias(entity_id, legacy_entity_ids), exposed to components through ComponentBase. get_history_wrapper then fills in the legacy entities' records from before the entity's own first record, so every history reader (fetch, PV calibration, ML load, charts) sees one continuous series. Where both were recorded the new entity wins. Legacy entities are read untracked so the history cache does not keep refreshing them, and are not read at all once the entity's own history covers the requested window. With no history anywhere the result is unchanged (None, raising when required). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Moving load_today, pv_today, import_today and export_today onto the site-level entities left every existing gateway site with no load, PV, import or export history under the new ids. automatic_config() now registers each site-level entity's serial-named predecessor (sensor.predbat_gateway_<suffix>_*_today, which is still published) as its history alias, so the history read before the site entity existed comes from there and the rename loses nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e changes When the inverter feeding the site-level *_today counters changed mid-day, the series jumped from the old counter's reading to the new one's. PredBat's history reads a rise as energy used and a small drop as a reset, so a 0.8 kWh step booked 12.79 kWh for a 12.00 kWh day and a -0.5 kWh step booked 11.49 kWh. The published value now carries on from the last value published that day, offset by the difference at the switch, and the offset is dropped when the source counter resets for a new day (a switch across midnight starts from the new counter). The source serial, its raw reading and the offset are kept in the entity's attributes, so a restart carries on the same way rather than stepping. With the offset the switch day books the same as a day without a switch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Problem
automatic_config()boundload_today,pv_today,import_todayandexport_todayto the first bound inverter's serial-named entities (sensor.predbat_gateway_<suffix>_load_today, ...). Load and PV history are fetched by entity id, so any change of the bound serial started that history from zero. That covers an inverter replacement, or a re-discovery that picks a different control target such as a second AIO moving control to the Gateway. The load forecast, PV calibration and ML load model then ran with no days of history.Fix
sensor.predbat_gateway_pv_today,_import_today,_export_todayand_load_today, which carry no serial, and bind the four args to them.automatic_config()records the slot 0 inverter, the one the energy args always used, as the source, so the plan sees the same data.*_todayentities are still published.PredBat.set_history_alias(entity_id, legacy_entity_ids), is exposed to components throughComponentBaseand is a no-op inMockBase.get_history_wrapperfills an aliased entity's history in with the legacy entities' records from before its own first record. Every history reader goes through it (fetch, PV calibration, ML load, charts), so all of them see one continuous series.No other gateway entity uses the new names: the site-level entities are
ems_total_*,sub<n>_*,onlineand theev_*charger entities, and a test checks each new id is written exactly once per status.Verification
The reviewer's cut-over simulation, run through PredBat's real fetch code: the old entity has 8 days of history and the new one 2 hours.
A switch of source mid-day, run through
utils.minute_data(true total 12.00 kWh). The "day without a switch" column is the same site sampled the same way:Limits
Tests
tests/test_history_alias.py(new, registered ashistory_alias):prepend_older_historyedge cases.get_history_wrapper: no alias; new entity with no history yet; partial history; a fully covered window that skips the legacy read; no data anywhere still fails; untracked legacy reads through the cache; removing aliases.test_gateway.py:test_mock_base.py: the delegate contract now coversset_history_alias.I reverted each piece individually (alias lookup, coverage skip, untracked legacy read, self-alias guard, the offset, the reset clear, restoring after a restart, the same-day check on a switch), and each revert makes a test fail.
./run_all --test gatewaypasses (288),--test history_aliasand--test mock_basepass, and./run_all --quickpasses.🤖 Generated with Claude Code