Repository navigation
fix(loadpoint): surplus orders any power on a charger with no step table - #1852
Merged
Merged
Conversation
Fuse protection read each phase's current as a magnitude, so 20 A of solar export counted as 20 A of import and a car never started on an exporting site. A phase now takes its direction from the same phase's power in the meter reading (P1 and the SDM630 report current as a magnitude); without that phase's power the current counts as import. An exporting phase counts at its reading for a rise and a start, and is never over the limit for an EV cut, since less EV load would raise its export. The sitesim meter now reports phase power. The two "export start" scenarios, two field-matrix rows and the rig's s2-16 pass. Six cloud rows that stopped failing on export now start and fail on the late readback; they carry that label. Five rows with phase_mode unset and no step table never order a step, a separate cause, labelled nostep. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A charger with no step table, as the settings page saves a new one, takes any power from its minimum to its maximum. surplus3PhaseSteps returned [0] for it, so surplus snapped every order to 0 W and the car never charged from solar. With no table the surplus steps are none, as SnapChargeW reads them, and the smallest step surplus may order is the charger's minimum: below it surplus still pauses. Stacked on the phase-direction fix: on master the export counted as import hid this. Two field-matrix rows pass; three cloud rows now start and fail on the late readback, and carry that label. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Review of the direction fix: with no check, a driver whose phase power had the wrong sign would turn 40 A of import into export, and the EV would never be cut. A phase now counts as export only when every phase power is present, they add up to the reading's total within a tenth or 250 W, and the phase's power is below -25 W and a quarter of what its current could carry. Otherwise it counts as import, as before the fix: a phase near 0 W, a reactive phase, a mismatched driver. Three more field-matrix rows (25 A, phase_mode unset, no step table, cloud chargers) never order a step either; they carry nostep, not readback. docs/safety.md says how the direction is read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tep-table # Conflicts: # go/internal/control/testdata/sitesim_field_known.txt
The check that phase powers add up to the total read meter.RawW in fuse_heat.go, a new direct read of cached telemetry. phaseCurrentsA now takes the total from its caller: the EV hard limit and its rooms pass the total they already read, the battery headroom clamp reads it once instead of four times, and SitePhases uses the health-gated OnlineMeterW, so a stale meter gives no phases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review: with phase_mode unset or auto and no step table, surplus now reached the one-phase day lock. A one-phase order is capped at 3,680 W, under the charger's 4,140 W minimum, so the lock gave it nothing for the rest of the day. With no table there is no one-phase ladder, and pickSurplusSteps returns no steps before the phase choice. The rig's s5-25 (25 A, surplus, auto, no table) now passes: the car charges 100 % of the time at 9.2 kW of 10 kW PV with no import, so its known line goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From #1853's review: the early return computed the three-phase steps before throwing them away, and an owner who removed the table on a day the charger was locked to one phase, or held on one, kept that lock until a restart. It now returns before anything else and clears the loadpoint's one-phase lock and phase hold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Second look at the no-table early return: it skipped the three-phase phase choice, so a no-table charger on auto got phase_mode auto, also at a 0 W pause, and Easee's driver picks one phase at 0 W and flips the contactor back on resume. The early return now records three phases as the session's choice, after clearing a one-phase lock; an owner's pin and a site that cannot run three phases still win in resolvePhaseMode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-step-table # Conflicts: # go/internal/control/ev_battery_headroom.go # go/internal/control/fuse_heat.go # go/internal/control/testdata/sitesim_field_known.txt
This was referenced Oct 25, 2026
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.
Based on master 0216fb6, which has #1849 (phase current takes its direction from the phase's power). On master before #1849, the export-as-import bug hid this one.
Cause
A charger with no step table takes any power from its minimum to its maximum. That is what the settings page saves for a new charger, and it is the home box's own setup.
surplus3PhaseStepsreturned[0]for it, so surplus snapped every order to 0 W and the car never charged from solar.A trace of
timing/16A/empty/none/fast2s/car3p/L1/surplusshowed 6,000 W of surplus, steps[0], smallest step 0, and no order for 30 min. On master the export-as-import bug hid this, because those rows already failed asexport.Change
SnapChargeWreads as any power between the minimum and the maximum.surplusMinStepW: with no table, the least surplus may order is the charger's minimum, so surplus still pauses below it, and the one-phase lock and the wake kick read the same minimum.pickSurplusStepsreturns before the phase choice and never locks the charger to one phase. A one-phase order would be capped at 3,680 W, under the 4,140 W minimum.Deleted: the
nosteplabel and its rows.Before and after
TestSurplusWithoutAStepTableOrdersTheSurplusTestSurplusWithoutAStepTableNeverLocksToOnePhase(phase_mode "" and auto, forecast 0, 9,310 W surplus, throughTick)readback, 8nostepreadback; thenosteplabel is gonetiming/{16A,25A}/empty/none/fast2s/car3p/L1/surplustiming/{16A,25A}/empty/none/{cloud60s,easee40s,easee120s}/car3p/L1/surplus(6 rows)readbackfor #1850go vetandgo test -p 2for loadpoint, control and cmd/ftw pass.TestSiteSimScenariosandTestSiteSimRandomHousepass.Independent review (Sonnet)
readbackrows hunt exactly like the stepped rows at the same timestamps.Limits
Hardware
Not run on real hardware. Real-hardware evidence is still needed: surplus charging on a charger with no step table, for example the home box's Easee.
🤖 Generated with Claude Code