Skip to content

fix(control): reserve pending battery rises before releasing relief - #1816

Draft
segran2 wants to merge 1 commit into
srcfl:fix/fuse-one-functionfrom
segran2:fix/pending-battery-relief-1789
Draft

segran2 wants to merge 1 commit into
srcfl:fix/fuse-one-functionfrom
segran2:fix/pending-battery-relief-1789

Conversation

@segran2

@segran2 segran2 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Ending battery discharge raises import just as adding charge does. The shared fuse allocator accounts for pending rises when increasing positive charge, but did not subtract them when deciding how much existing relief may end. Successive commands can therefore spend the same measured phase room twice. The mirrored export pass has the same problem when ending battery charge.

Stacked on #1789, targeting fix/fuse-one-function at c60da23df78a0355f496fb3e3691898e19c7d7cc. This is a narrow follow-up to that implementation, not a merge of #1763's different EV-reservation policy. Retarget after #1789 lands; do not merge independently into master.

Change

Include pendingW in capBatteryCharge's relief shortfall, as it is already included in positive charging-rise room. Import and export use the same function with reversed signs. Existing relief availability, battery floor/direction bounds and the no-new-relief condition are retained. No additional telemetry, settings, timing changes or driver behavior.

Reproduced case

  • 25 A three-phase site, 230 V, 1 A working margin; fresh phases 22.3 / 12.3 / 12.3 A, total 10,787 W.
  • Battery still measures −2,000 W. A −1,000 W command sent two seconds ago has not yet arrived.
  • Next target is 0 W: another 1,000 W import rise on top of the 1,000 W already pending.
  • Available phase room is (24−22.3)×690 = 1,173 W.
  • Before: 0 W allowed, conditional resulting phase 25.199 A.
  • After: retain −827 W, conditional resulting phase 24.000 A.

The symmetric export case retains +827 W rather than ending charge into excessive export. These are balanced-response calculations assuming unchanged other loads and that the target arrives before another correction; they are not hardware measurements or evidence of fuse operation.

Validation

  • All six new import/export regression cases fail before the change and pass afterward: direct allocation, full ComputeDispatch with bounded manual zero target, and ordinary idle dispatch.
  • Additional tests cover pending/settled commands, sufficient room, unavailable relief, floor-bounded relief and no existing relief. Complete-dispatch fixtures disable the separate slew limiter to isolate the fuse admission decision; no real settings were changed.
  • Full control suite passes, including existing golden/scenario tests, without golden updates or added failure exemptions.
  • On commit c2246d10d6dcbbb6df2fdf6d328b6b784b61c1f5: make verify passes; full go test -race ./internal/control ./internal/telemetry ./internal/loadpoint -count=1 passes; telemetry-read ratchet and git diff --check pass.
  • Docker-context and live Avahi checks were skipped because no Docker daemon was available. No hardware acceptance is claimed.

This addresses the independent pending-battery regression found while comparing #1763 and #1789. It does not resolve the separate EV-under-delivery reservation-policy decision, establish hardware acceptance or change the running household installation.

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.

1 participant