Repository navigation
feat(fetch): warn when car_energy_reported_load is On but the load sensor excludes the charger - #5320
Open
chalfontchubby wants to merge 10 commits into
Open
chalfontchubby wants to merge 10 commits into
chalfontchubby wants to merge 10 commits into
Conversation
…nsor excludes the charger (#5318) With switch.predbat_car_energy_reported_load On, Predbat subtracts car_charging_energy from the load history and, for an Octopus Intelligent car without car_charging_now, reads low house load as the car not charging. Against a load sensor that excludes the charger, the first empties the load history and the second cancels dispatches that are really charging (#5317) - and nothing in the logs pointed at it. A load sensor that includes the charger can never read less than the charger's own energy over the same window, so count the half hours of the last day where car_charging_energy beat the load by a margin (1 kWh minimum, 0.5 kWh margin to absorb lag between the two sensors) and log a one-time Warn: at two or more, suggesting the switch be turned Off and car_charging_now set to the charger's power or status sensor. On #5317's debug dump it fires on 8 of the last 24 half hours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lag and gaps (#5318 review) - A window now needs the charger's energy to exceed twice the load rather than the load plus 0.5 kWh: at 11 kW a 5 minute lag between the two sensors already moves 0.9 kWh, so a fixed margin warned on a correctly configured system. A ratio tolerates a lag of up to half the window at any charger power; #5317's windows are all above 2. - A window with no load at all is skipped - a house always draws something, so a flat stretch is the load sensor missing data. - Once warned, the warning is not re-armed until no window shows the mismatch, as the windows move with now and a borderline count can flip from one cycle to the next. Tests: 11 kW over two sessions with +/-5 and 10 minute lag, a load gap (both fail on the old rule), and the re-arm hysteresis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed_load check (#5318 review) A cloud-polled load sensor (GE Cloud caches up to 30 minutes) can be many minutes behind the charger's energy sensor, so the half hour in progress reads short and could count as evidence on a correct setup. Scan from one window back. Also drop the end-of-history key check, which never fires on the padded load history, and say instead that missing minutes read as no increment and are skipped with the empty-load windows; and make the warning's advice conditional on car_charging_energy being only the car charger, since the docs still allow other loads in it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d-window (#5318 review) The 2x ratio only protected windows wholly inside a charge session. Where a session starts part-way through a window, a load sensor that includes the charger but reports 10-15 minutes late shows only part of that charge, so the window counted. Two or three Octopus Intelligent dispatches a night were enough to warn a correctly configured user to turn the switch Off. A window now counts only if the car energy exceeds twice the load in that window shifted by every offset up to CAR_ENERGY_LOAD_CHECK_LAG (15) minutes either way. Running totals keep it to one subtraction per window and shift. On #5317's debug dump it still finds 7 of the original 8 half hours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…5318 review) minute_data() interpolates across a gap inside the history rather than leaving it flat, so only a stretch before the history or padded over a reset reads as no load; say so, and that a long outage over a charge can still count. The load history is only emptied when car_charging_hold is On as well. Give the test's nested load() helper a docstring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The warning-only change is consistent with its documented heuristic and has strong boundary-case coverage.
0 open findings
What changed in this PR
Adds a heuristic warning for likely misconfiguration of car_energy_reported_load.
Changes:
- Detects repeated car-energy/load mismatches using configurable thresholds.
- Adds one-time warning and re-arm behavior.
- Documents and comprehensively tests the detection logic.
| File | Description |
|---|---|
docs/car-charging.md |
Documents the warning and remediation. |
apps/predbat/const.py |
Defines detection thresholds. |
apps/predbat/fetch.py |
Implements and invokes mismatch detection. |
apps/predbat/predbat.py |
Initializes warning state. |
apps/predbat/tests/test_car_energy_reported_load.py |
Covers detection, lag, gaps, and warning throttling. |
apps/predbat/unit_test.py |
Registers the new tests. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…reported-load-5318 Conflict resolution: - apps/predbat/predbat.py (PredBat.reset init block): kept this branch's new self.car_energy_reported_load_warned = False initialiser, and took main's reworded car_slot_owner comment (#5413: the claim covers only octopus_ready_time/octopus_charge_limit, not octopus_intelligent_slot). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plan (#5318) compare.py re-runs fetch_sensor_data(save=False) once per candidate tariff (now via run_comparison(), merged from main). The check reads and writes the live car_energy_reported_load_warned flag, so a tariff config that turns the switch Off would clear the flag and re-arm the warning every compare cycle. Gate it on save, as fetch already does for the dispatch timeline log, and pin the gate in the test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r_energy_reported_load check (#5318) Replaces the source-text check from the previous commit, which would still pass if the guarded call moved or its result were ignored. Test 13 now runs the real fetch_sensor_data() on a fresh PredBat (so nothing it resets leaks into the shared fixture, #5079), with the history readers stubbed empty: - save=False with the switch Off and the live flag warned: the check is not called and the flag stays set; - save=True: the check runs once and clears the flag. With the `if save:` guard removed both assertions fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…load warning (#5318 review) Test 13 stubbed both history readers empty, so the check cleared the flag whatever the switch said and only the call count told pass from fail. It now feeds a load series that excludes the charger, captures the log, and runs live cycle (switch On, warns) -> comparison run (save=False, switch Off) -> next live cycle. Without the gate the comparison run clears the flag and the next live cycle logs the warning a second time; with it the warning is logged once. The docstring now says the fetch still sets the process-wide metrics() gauges rather than claiming nothing leaks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#5318 review) The stand-ins only answer for load_today and car_charging_energy, so set both on the fresh instance instead of relying on coverage/apps.yaml, and drop ge_cloud_data so the load history cannot take the GE Cloud path that bypasses minute_data_load(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Written by Claude, on behalf of @chalfontchubby.
Fixes #5318 (part 2; part 1 is declined on the issue, with the workaround).
Summary
With switch.predbat_car_energy_reported_load On (the default), Predbat assumes the car charger is inside the house load sensor. If it isn't, two things go wrong and nothing in the logs says why:
car_charging_holdsubtractscar_charging_energyfrom a load history that never contained it, so the load history empties.car_charging_now, the low-load test reads the car-free house load as "car not charging" and cancels dispatches that are really charging. That is battery exporting while EV charging and battery set to demand in cheap rate with IOG #5317, where it happened 7 times in one night.A load sensor that includes the charger can never read less than the charger's own energy over the same period. This PR checks that, and logs a warning once when it clearly fails:
How it decides
check_car_energy_reported_load()runs infetch_sensor_data()straight afterload_car_energy(), when both series are still raw. It runs only for the live plan (save=True), not for the per-tariff re-fetches the tariff comparison makes, so a comparison tariff that turns the switch Off can't reset the warning.CAR_ENERGY_LOAD_CHECK_LAG).CAR_ENERGY_LOAD_CHECK_*inconst.py.docs/car-charging.mddescribes the warning under the switch.Checked on #5317's debug dump: it fires on 7 of the last 24 half hours. The car recorded 2.6 to 3.5 kWh per half hour against 0.3 to 1.0 kWh of house load, and the lowest ratio against the shifted load is 2.7.
Testing
tests/test_car_energy_reported_load.py, registered ascar_energy_reported_load, covers:fetch_sensor_data()over a live cycle (warns), a comparison run withsave=Falseand the switch Off, and the next live cycle: the warning is logged once, not re-armed by the comparison runEach rule was checked by disabling it and confirming its test fails.
./run_all --quickand./run_pre_commitpass.Not addressed
car_charging_energy.Possible follow-ups
car_charging_power(documented as car only) ascar_charging_nowevidence whencar_charging_nowisn't set.🤖 Generated with Claude Code