Repository navigation
fix(loadpoint): solar-only auto runs on three phases above the minimum - #1853
Merged
Merged
Conversation
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. |
frahlg
force-pushed
the
fix/surplus-auto-three-phases
branch
from
October 25, 2026 14:38
ca2cbb5 to
4ad0798
Compare
frahlg
added a commit
that referenced
this pull request
Oct 25, 2026
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>
frahlg
force-pushed
the
fix/surplus-auto-three-phases
branch
2 times, most recently
from
October 25, 2026 15:21
4e40379 to
52c1777
Compare
frahlg
added a commit
that referenced
this pull request
Oct 25, 2026
…ble (#1852) * fix(control): phase current takes its direction from the phase's power 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> * fix(loadpoint): surplus orders any power on a charger with no step table 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> * fix(control): a phase exports only when its power shows it clearly 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> * fix(control): the sign guard takes the site total from its caller 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> * fix(loadpoint): a charger with no step table never locks to one phase 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> * fix(loadpoint): no step table returns first and clears an old lock 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> * fix(loadpoint): a charger with no step table holds three phases 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> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Site rig s5s: a surplus-only loadpoint on phase mode auto with Easee's steps stayed on one phase at 9.3 kW of surplus. The live surplus picked three phases at the first tick. The next tick the plan, which showed no PV, set the day's one-phase lock, and nothing ended it that day. Each forecast window starts now, so its peak is never below the surplus measured now. That reading counts only up to the average the pause gate keeps, so one high reading does not switch to three phases. The day's lock gives way to surplus above the three-phase minimum once it has held for 30 min, and it waits for a three-phase choice to hold as long. Three phases start at 6 A each, as PlanningSteps counts them: 3,680 W is 16 A on one phase. Counted as three-phase, 3.7-4.1 kW of surplus picked three phases and ordered 4,140 W, which imports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frahlg
force-pushed
the
fix/surplus-auto-three-phases
branch
from
October 25, 2026 15:32
52c1777 to
3a32dc1
Compare
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.
Built on #1852 (surplus on a charger with no step table), now merged. This PR is one commit on master. It touches
pickSurplusStepsandsurplus3PhaseSteps, which #1852 also changed.Fixes the site rig's known failure s5s-25: "
autostays on one phase at 9 kW surplus". s5-25 (no step table) is #1852's.Cause
The rig's loadpoint is surplus-only, phase mode auto, with Easee's steps. It has 9.3 kW of surplus, and its plan shows no PV.
pickSurplusStepspicks three phases.A second fault sits under it.
surplus3PhaseStepscounted 3,680 W, which is 16 A on one phase, as a three-phase step. So the three-phase minimum in the phase choice was 3,680 W, not 4,140 W.Change
phaseSwitchMinHold). Three phases then hold for 30 min too.PlanningStepscounts them for planned charging.surplus3PhaseStepskeeps fix(loadpoint): surplus orders any power on a charger with no step table #1852's branch for no table and1p.PhaseSplitWstill tells anautodriver where to split. It no longer sorts the table, and its doc comment says so.selectPhaseLocked3Precords three phases once; this PR'sselectPhaseLockedrecords either choice with its time, which the near-term dwell needs.Smaller effects: a one-phase charger left on an empty mode, and a table on a one-phase site, now pause below their smallest step (1,380 W), not below 3,680 W. A bat-SoC unlock (
SurplusOnlyfalse) still never sets the day lock.Before and after
TestSurplusAboveTheThreePhaseMinimumRunsThreePhases: 9.3 kW, plan without PV, 45 minTestSurplusBelowTheThreePhaseMinimumRunsOnePhase: 3.8 kW (rig s5t)TestSurplusOnePhaseYieldsAfterTheHold: 2 kW, then 9 kW, then 2 kW; dwell and day lockTestSurplusOneHighReadingKeepsOnePhase: 1.5 kW and one 4,300 W readingTestSurplusOnePhaseOfferStaysWithinTheCharger, three-phase casesitesim_field_known.txtWith the window average alone as the floor,
timing/25A/auto/mixed/fast2s/car3p/L1/surplusfailedidle. Export fell from 9 kW to 3 kW, the average held three phases for 8 s, the pause gate paused, and its 35 s hold kept the car idle. Taking the lower of the reading and the average keeps that row green.go/test/site/scenarios_test.go: deleted s5s-25'sknownline, since the rig fails a known criterion that passes. #1852 already deleted s5-25's. The rig passed s5s-25 on 4ad0798, this commit on an earlier #1852 base, with both planner engines. Later rebases changed only the lines next to #1852's no-table return.go vetandgo testfor./internal/...,./cmd/ftw/...and./test/site/pass, the field matrix among them (342 cases, the known rows unchanged).go test -racepasses forloadpointandcontrol. Since #1852 merged, this PR targets master.An independent review (Sonnet) found no blocker. It found that one reading chose the phase, fixed with the reading-and-average floor. A second look after the rebase found nothing in this diff.
Open
🤖 Generated with Claude Code