Skip to content

fix(control): an unplugged car is no EV cut the battery waits for (#1674) - #1713

Merged
frahlg merged 2 commits into
masterfrom
1674-ev-cut-pool-change
Oct 17, 2026
Merged

frahlg merged 2 commits into
masterfrom
1674-ev-cut-pool-change

Conversation

@frahlg

@frahlg frahlg commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #1706 for its Codex findings. #1674.

Problem

pendingEVCutW counts the EV cut Core sent during an overage of the hour's import limit, so the battery does not discharge for the same watts. It took the pool's total offer when the overage began, less this tick's total. Two Codex findings:

  1. On fix(control): the battery leaves the hour's overage to the EV cut Core sent (#1674) #1706 (ev_fuse_budget.go:328): with two managed chargers, unplugging one during the overage dropped its offer from the total. That counted as a cut Core sent, although the meter may already show the unplug, so battery relief was held back for up to 20 s.
  2. On this PR's first version (ev_fuse_budget.go:138): restarting the whole baseline when a car left also dropped a cut already sent to a car that stays. The battery then covered that cut too, and the site could export when it landed.

Change

The baseline is now per charger:

  • When a run over the hour's limit begins, the EV guard notes each plugged charger's offer (overOffers).
  • pendingEVCutW is the sum, over chargers still plugged, of max(0, offer at run start − offer this tick).
  • A car that leaves drops out. A car that joins has no start offer and counts 0.
  • The 20 s cap stays, and only our own commands count.

For the offers this tick per charger, main.go now calls ctrl.SetEVCommanded(lpStatesSnapshot). It sets EVCommandedW as before, plus a per-driver map from the new loadpoint.CommandedEVPowerByDriver, which keeps a stopped car at 0 W. CommandedEVPowerW now sums that map, with the same result as before. The key is the charger driver, as CommandedEVPowerW already counts a driver once; that is one per loadpoint in the usual case.

Results

Test #1706 (master) First version of this PR Now
TestUnpluggedCarIsNoCutTheBatteryWaitsFor: two cars at 5,520 W; car b unplugged during an 880 W overage, no cut sent relief 0 W (5,520 W counted as a cut) 880 W 880 W
TestCutOnStayingCarStillWaitsWhenAnotherLeaves: Core stops car a (10,350 W) during an overage; car b (4,140 W) unplugged 5 s later; a's stop lands at 10 s battery 0 W, no export battery −4,850 W at 5 s (meter −2,850 W once a's stop lands) battery 0 W, lowest meter 2,000 W, no export

The earlier tests in the file keep their results.

Limits

  • No hardware run.

Test plan

  • make verify
  • bash .github/scripts/check-telemetry-reads.sh origin/master: none added
  • Each new test fails on the version named in the table and passes here

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T16:40:23.199786Z 753aa85 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 753aa856c7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread go/internal/control/ev_fuse_budget.go Outdated
frahlg and others added 2 commits October 17, 2026 19:46
)

Codex on #1706: with several managed chargers, unplugging one car during
an overage of the hour's import limit dropped its offer from the pool.
pendingEVCutW counted that drop as a cut Core sent, although the meter may
already show the unplug, and held back battery relief for up to 20 s.

The EV guard now notes which loadpoints are plugged. When a car leaves or
joins, the run's baseline restarts at the pool's offer then, so only cuts
sent to cars still plugged count. Our own commands only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
…es (#1674)

Codex on #1713: restarting the whole pool's baseline when a car left also
dropped a cut already sent to a car that stays. The battery then covered
that cut too, and the site could export when it landed.

The EV guard now notes each charger's offer when a run over the hour's
limit begins. pendingEVCutW sums, over chargers still plugged, the start
offer less this tick's offer. A car that leaves drops out; a car that
joins has no start offer. main.go hands Core this tick's offers per
driver through SetEVCommanded, from loadpoint.CommandedEVPowerByDriver,
which keeps a stopped car at 0 W. Our own commands only; the 20 s cap
stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@frahlg
frahlg force-pushed the 1674-ev-cut-pool-change branch from 753aa85 to af68921 Compare October 17, 2026 17:49
@frahlg
frahlg merged commit 6308d04 into master Oct 17, 2026
23 checks passed
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