Skip to content

feat(ev): Start becomes "charge now → target", releasing back to the plan - #1007

Merged
frahlg merged 1 commit into
masterfrom
1002-ev-charge-now
Aug 30, 2026
Merged

feat(ev): Start becomes "charge now → target", releasing back to the plan#1007
frahlg merged 1 commit into
masterfrom
1002-ev-charge-now

Conversation

@frahlg

@frahlg frahlg commented Aug 30, 2026

Copy link
Copy Markdown
Member

Part 2 of #1002. Re-opened #1005 against master (the original was auto-closed when its stacked base branch was deleted on #1004's merge). #1004 is merged, so the diff here is only this feature's delta.

Problem

The modal's Start button installs a persistent manual hold that pins the wallbox at a fixed amperage until unplug — the planner is silently dead for the whole session. On 2026-08-29 that meant an 11 kW offer held all night against a car that was already at its own charge limit, with the per-phase fuse clamp fighting the hold the entire time (worst phase measured 23 A on a 16 A main fuse).

What this does

  • loadpoint.ManualHold gains ReleaseAtSoC (0–1): once the loadpoint's inferred (or BMS-anchored) SoC reaches it, the controller clears the hold and the same tick falls through to automatic surplus/plan dispatch. Persisted with the hold across restarts. A hold without a target keeps the legacy pin-until-Stop-or-unplug contract; unplug and the vehicle-declined debounce still release as before.
  • POST /api/loadpoints/{id}/manual_hold accepts release_at_soc_pct (0–100, validated); GET mirrors it; loadpoint state carries manual_release_soc.
  • The Start button becomes "Charge now → 80 %" (the schedule's target when set, 80 % otherwise). The manual tab and the feat(ev): say why the charger is (not) charging and when it will #1004 plan strip both explain the hand-back: "Charging now at 11.0 kW → returns to plan at 80 %."

Verified in a browser (running dev stack)

Pressed "Charge now → 80 %" in the rendered modal → hold installed with release_at_soc_pct: 80 → corrected SoC to 85 % via /soc → controller logged loadpoint manual hold released — charge-now target reached (soc=0.85, release_at_soc=0.8) and the very next dispatch was the plan's, not the hold's.

Tests

  • TestChargeNowHoldReleasesAtTargetSoC — holds below target, releases at target, same-tick plan dispatch
  • TestLegacyHoldWithoutTargetNeverSoCReleases — legacy contract untouched
  • web/ev-charge-now.test.mjs — button contract, POST body, both status texts (445 web tests green)

🤖 Generated with Claude Code

https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi


Note

Medium Risk
Changes EV dispatch control (manual hold lifecycle and when MPC regains authority); behavior is tested but wrong SoC inference could release early or late.

Overview
EV manual Start is now a bounded “charge now” boost instead of pinning the planner off for the whole session. The controller adds ReleaseAtSoC on ManualHold: while active it still commands the slider’s watts, but clears the hold when estimated SoC reaches the target and dispatches the MPC plan on the same tick. Holds with no release target keep the old pin-until-Stop-or-unplug behavior.

API and UI wire this through: POST /api/loadpoints/{id}/manual_hold accepts release_at_soc_pct (0–100, validated); loadpoint state exposes manual_release_soc. The modal renames Start to “Charge now → {target} %” (schedule SoC or 80 % default), posts release_at_soc_pct, and updates status copy in the manual tab and plan strip.

Tests cover SoC-triggered release with same-tick plan dispatch, legacy holds unchanged, and a small web contract test for the button/POST body.

Reviewed by Cursor Bugbot for commit 84e956b. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 30, 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-08-30T07:58:26.159573Z d47879c 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.

…plan

Field report (#1002): a Start hold pins the wallbox at a fixed amperage
until unplug, silently disabling the planner for the whole session —
observed as an 11 kW offer held all night against a car that was
already full, with the fuse clamp fighting it the whole way.

ManualHold gains ReleaseAtSoC (0–1): once the loadpoint's inferred (or
BMS-anchored) SoC reaches it, the controller clears the hold and the
same tick falls through to automatic surplus/plan dispatch. The target
persists with the hold across restarts; a hold without one keeps the
legacy pin-until-Stop-or-unplug contract, and the existing releases
(unplug, vehicle-declined debounce) still apply.

POST /api/loadpoints/{id}/manual_hold accepts release_at_soc_pct
(0–100), GET mirrors it, and the loadpoint state carries
manual_release_soc so the UI can say where the boost stops. The modal's
Start button becomes "Charge now → 80 %" (schedule target when set,
80 % otherwise) and both the manual tab and the plan strip explain the
hand-back.

Verified in the running dev stack: pressed the button, hold installed
with release_at_soc_pct 80; corrected SoC to 85 %; controller logged
"charge-now target reached" and released to plan dispatch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi
@frahlg
frahlg force-pushed the 1002-ev-charge-now branch from d47879c to 84e956b Compare August 30, 2026 07:56
@frahlg
frahlg merged commit 4082a64 into master Aug 30, 2026
8 checks passed

@cursor cursor 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.

Approved: Cursor Bugbot completed successfully with no findings that need human review, and no approval policy requires extra review. Reviewers were not assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

frahlg added a commit that referenced this pull request Sep 4, 2026
"Charge now → target" (#1007) released the hold the moment the SoC
estimate reached the schedule target. On a charger that cannot read the
car the estimate is a guess, and when it already sat at the target the
button released itself on the next tick: five presses, no charge
(box log 2026-09-04 06:15–06:18). The manual tab no longer sends a SoC
release; Start runs until the car stops asking for current, Stop, or
unplug, and the plan takes over after that. The API refuses a
release_at_soc_pct the estimate already meets (409) instead of
installing a hold that clears on the next tick.

Refs #1002.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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