Skip to content

fix(control): reserve EV demand until offered power is delivered - #1763

Draft
segran2 wants to merge 7 commits into
srcfl:masterfrom
segran2:test/ev-priority-offer-reservation
Draft

segran2 wants to merge 7 commits into
srcfl:masterfrom
segran2:test/ev-priority-offer-reservation

Conversation

@segran2

@segran2 segran2 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

An accepted EV current offer could be counted as if the car already consumed that power. Optional battery charging could then occupy the room the EV still needed. For example, a 10.35 kW offer with about 4.2 kW delivered must not be treated as 10.35 kW already included in the site meter.

This PR reserves the unmet EV demand before optional battery charging, including Charge now, and keeps that protection through pending pause and battery-relief transitions. Feedback wording is tracked separately in #1762.

Implementation

  • Credit only the smaller of the lowest recent EV offer and qualified measured EV delivery. Missing, unhealthy, unavailable, stale, future or site-unaligned delivery earns no credit.
  • Keep the clamp active while a managed EV pause propagates; a zero offer does not prove that the physical EV load has disappeared.
  • Ending battery discharge also raises import. Retain only previously commanded discharge that is still permitted by existing battery bounds/health/SoC checks while the phase room cannot absorb its removal. Do not invent new discharge or reserve an EV demand that admission has not allowed.
  • Account for pending battery import increases before releasing more relief. A fresh, healthy, source-qualified battery observation aligned with the site meter may establish that a previous increase arrived; otherwise retain the existing conservative command window.
  • Qualify EV and battery control power inside telemetry accessors under the store lock. Control adds the site-time alignment and reservation calculations; no new direct cached-telemetry reads or exceptions are introduced.
  • Preserve required measured export relief and existing EV admission, stop/default and protection timing. No fuse settings, user priorities, driver or hardware commands are changed by this source PR.

The branch now merges official v0.155.1-beta.1 in 6d7b714, preserving the earlier PR commits. Follow-up commit 4372354480671b1d22df1c80a6f5c5d045ac4e30 incorporates the previously local transition fixes plus the reviewed telemetry-accessor change and additional regressions. These follow-ups are now in the PR branch; they are no longer only a local hardware candidate.

Validation on 4372354 — 23 October 2026

  • make verify: passed, including all Go suites, simulation/regression matrix, script checks, vet and build. Docker context and live Avahi checks were skipped because no Docker daemon was available.
  • Targeted race tests passed in control, telemetry and loadpoint for EV/battery reservation, recorded incident cases, control-power qualification, joined EV/battery behavior, fuse/export, stale/fault and stop paths.
  • Telemetry-read ratchet and git diff --check: passed.
  • Three new integrated regressions fail against the pre-follow-up clamp and pass after the fix: managed pause releasing unmeasured room; ending existing discharge beyond phase room; spending an unseen import increase twice. The before test retains helper declarations solely so the unchanged old pipeline can compile.
  • Eligibility tests reject stale/future/offline/faulted/missing measurements, invalid source validity and unavailable/nonfinite power. Relief tests retain existing direction blocks, explicit zero discharge caps, missing/low SoC and no-prior-command protections.
  • Six previously known own-raise failures are removed from the simulation expectation file because they now pass. 23 existing known idle failures remain. No new known-failure exemptions were added. A green expected-failure matrix is not universal behavioral acceptance.
  • The Explain EV under-delivery using site fuse headroom and concurrent battery charging #1761 simulation now asserts the safer battery ceiling rather than requiring the old high battery consumption.

A complete control/telemetry/loadpoint race run also passed during integration; the final commit was verified with the targeted race command above after the final meter-snapshot cleanup.

Hardware evidence and limits

The detailed 23 October allocation/command trace and earlier reports remain in the discussion. They used a locally packaged v0.155.1-beta.9002 candidate, not an installation built from final PR commit 4372354.

Full EV delivery was observed with 1.5 kW battery charging, and stepped EV/Pixii runs showed Core retaining a 15 A EV command while limiting the battery. Easee nevertheless lowered its own allocated current and pilot; a complete driver command trace found no coincident FTW pause, phase change or reduced current command. The exact Easee allocation decision remains unresolved.

Keep the aborted battery-first run's 25.33 A measured sample in the safety record. Later runs peaked at 18.95, 23.74 and 24.13 A; these do not erase the earlier sample or exclude unsampled transients. Internal reservation before/after values were not captured on hardware. Final-commit hardware acceptance, wider import/export scenarios and the separate 6 A start delay remain open. This update performs software tests only and changes nothing on the installed FTW.

Integration conflict — keep draft

#1789 deletes clampEVBatteryHeadroom and explicitly adopts a different reservation policy; #1782 also touches the phase calculation. This branch continues the owner-requested #1763 correction on the released baseline and does not merge, overwrite or validate those PRs. Resolve the control-policy/dependency choice before merge; these branches must not be treated as independently compatible fixes. No reviewers were automatically requested and no merge/release is performed.

Pending import across batteries (24 October 2026)

Keep pending battery import when that battery has no target in the current dispatch. A fresh reading from another battery can no longer clear its reservation. The existing command expiry and EV reservation policy stay in place.

This follow-up merges master 2d7c8eba41f0d247c8833029fc33bd60f32aa04b into the existing branch and adds the fix, a changeset and TestEVBatteryPendingImportAcrossTargets.

Validation on 7361f9d0818a106789b97e37fca09954afd105a7:

  • The nine-case regression matrix covers allocation, idle and manual dispatch. The three cases with a pending battery absent from the current targets fail before the fix; all nine pass after it.
  • Full make verify, control/telemetry/loadpoint race, make e2e, npm test and the telemetry-read check pass.
  • The full Go site simulator passes with its existing expectations: 340 field cases, including the same 23 known idle failures. No known-failure or golden records changed.
  • The pinned device-simulator rig passes the short set and the two additional scenarios s10-25 and s15bat-16, through the real Core binary, Modbus and OCPP.

Docker-context and live-Avahi checks were skipped on this host. Simulator results do not establish physical equipment or Easee firmware acceptance. The PR remains draft; no merge, release or box update was made.

Signed-off-by: Segran <goran@andersson-stehag.se>
Signed-off-by: Segran <goran@andersson-stehag.se>
@segran2 segran2 changed the title test(control): reproduce lost EV priority when stable offers are not delivered fix(control): reserve EV demand until offered power is delivered Oct 20, 2026
Signed-off-by: Segran <goran@andersson-stehag.se>

segran2 commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Field-test report — 2026-10-20 (partial pass)

Tested commit 387b7d7f9c6d2b351afe27377b50d510d6220c20 in FTW v0.154.2-beta.1 on Raspberry Pi (aarch64), with Easee and Pixii.

Passed / observed

  • FTW service started and remained operational during the observed test window; no errors appeared in the filtered logs supplied.
  • Easee/FTW reported measured EV power of 0 W while the vehicle was connected but not charging.
  • Relevant control and telemetry tests passed: go test ./internal/control ./internal/telemetry -run 'TestEVBattery|TestOnlineEVControlPower' -count=1 -v. This includes unrealized offers, stale/offline/faulted telemetry, reservation and phase/headroom scenarios.
  • Reviewed control path: SetEVFuseDemands(...) precedes ComputeDispatch(...), whose target processing calls clampEVBatteryHeadroom(...).
  • Pixii continued receiving stable discharge setpoints (~−1.2 kW in EMS sign convention). A 60-second scoped POST /api/battery/manual_hold requesting charge, power_w=2000, driver=pixii was accepted at 16:29:06. Pixii's EMS setpoint transitioned from approximately −1.3 kW before the hold to +982 W at 16:30:05, consistent with gradual ramping and successful positive charge dispatch.

Not yet demonstrated in the field

  • No direct observation of a positive evFuseDemands snapshot and a before/after reduction specifically attributable to clampEVBatteryHeadroom. The sub-2 kW Pixii target during the 60-second hold cannot be attributed to EV reservation rather than slew/other limits. Therefore, the EV-specific battery-charge clamp is unit-tested but not conclusively field-verified.
  • Setpoint logs show commands, not independent confirmation of actual Pixii measured power.

Outcome: Partial field-test pass; no regression observed in the tested conditions. No code changes proposed from this test. A conclusive EV-headroom field check would require diagnostic visibility into EV demand, qualified realized EV power, and battery targets before/after the clamp.

segran2 commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Hardware follow-up — 22 October 2026: distinguish Core admission from Easee startup

Test environment: released Core v0.155.0-beta.1 with local Easee driver 1.3.12. This is not a test of PR head 387b7d7 and does not establish acceptance of this PR's allocation change. Times below are Europe/Stockholm.

  • A seven-minute direct 6 A / 4140 W request from confirmed idle eventually started without any higher-current offer. Resume acknowledgements were logged at 01:24:10, 01:24:40 and 01:25:15. A no-power warning followed at 01:25:45. Easee first reported a positive 6 A pilot at source time 01:29:32, 5 min 22 s after the initial resume. Positive power was received at 01:29:40 and subsequently reached approximately 4.184 kW; the site meter also confirmed the load increase. No new resume appears in the captured log at the actual start. Earlier three-minute no-start runs therefore do not establish that 6 A cannot start.
  • A later repeated 7 A start followed by reduction to 6 A succeeded: approximately 4.764 kW at 7 A, then a source-timestamped 6 A pilot at 03:28:07 and approximately 4.130 kW. The car was first paused from scheduled charging and confirmed at 0 W / 0 A.
  • Importantly, Core initially admitted 0 W with reason fuse_limit during that 7 A request, before later sending 4830 W. One captured interval had approximately 1.83 kW grid import and phase currents 6.257 / 1.817 / 1.422 A, with Pixii at 0 W. This is an observation requiring investigation, not proof that the fuse guard was incorrect: internal historical demand/reservation state was not captured. End-to-end wait time must be split into Core admission time and charger response time.

The late 6 A start is consistent with an Easee firmware/allocation delay, but the internal cause and the effect of repeated resume commands remain unproven. A single-resume long-duration comparison remains useful. The early no-power warning preceded real delivery and should be reviewed separately from allocation correctness. No automatic over-request startup boost or safety-limit change was introduced.

Temporary commands were removed after the tests and ordinary planning resumed. These observations do not close the outstanding EV-priority/headroom acceptance criteria.

segran2 commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Consolidated hardware and Core investigation — 21–22 October 2026

This consolidates the later results, including the follow-up to the earlier comment. Partial hardware success; outstanding faults remain. Keep acceptance open. #1763 is the primary location because allocation/admission is central; the feedback findings below are relevant to #1762 but are not claims about its unmerged implementation.

Environment and evidence boundary

The later runs used released Core v0.155.0-beta.1 and locally modified Easee 1.3.12, not this PR's head and not the older v0.154.1-beta.2 backport described above. Consequently, these results neither validate nor disprove this PR's exact implementation. Configured main fuse: 25 A, three-phase. No raw vendor/Pixii control bypass was used. Temporary holds were removed or expired and ordinary planning resumed. Times below are Europe/Stockholm.

Observed successes

Scenario Result
Natural scheduled start, 21 Oct 23:45 15 A pilot at 23:45:08; first positive vendor power source time 23:45:14; approximately 10.375 kW by receipt 23:45:35. Initial recorded phase maximum 18.35 A. Subsequent natural stop was observed at 0 W after midnight.
Import ceiling 7500 W, five-minute request Core offered 8 A / 5520 W with import_limit; approximately 5472 W delivered. No positive-to-zero cycling during the hold. Recorded grid maximum 6988 W and phase maximum 12.75 A. Ceiling restored to disabled afterward. This ceiling controls hourly average import, not a strict instantaneous 7500 W cap.
EV starts while Pixii already charges Pixii measured 6024 W before the EV request. EV reached approximately 8307 W; battery charging fell through approximately 5022 / 4300 / 3615 W to zero, then recovered. Recorded phase maximum 24.28 A.
7 A start followed by 6 A Repeated successfully: approximately 4.76–4.81 kW at 7 A, then approximately 4.13–4.23 kW with a reported 6 A pilot.

EV priority remains incomplete: in the battery-first run, 15 A was requested but Core later offered only 13 A with fuse_limit while Pixii recovered toward 6 kW. The last changed pilot observation was 12 A and delivery approximately 8.3 kW. Full 15 A priority and command-to-pilot propagation were not established.

Direct 6 A start: delayed, not demonstrated impossible

Earlier three-minute runs ended without power; longer observation changed the conclusion:

  • Idle start: resume acknowledged at 01:24:10, repeated at 01:24:40 and 01:25:15. A no-power warning appeared at 01:25:45. Positive 6 A pilot source time was 01:29:32, 5 min 22 s after the initial resume; positive power received at 01:29:40, subsequently approximately 4184 W.
  • Explicit pause/restart: verified 0 A / 0 W, then requested 4140 W at approximately 03:31:35. Core initially sent zero with fuse_limit. First captured admission was 03:34:29.94, resume acknowledged 03:34:30.28. Positive 6 A pilot source time was 03:40:09, 5 min 39 s after resume; delivery subsequently approximately 4146 W.
  • No higher-current startup offer was issued in either direct 6 A run. Site-meter changes support real delivery.

These runs separate Core admission delay from a subsequent charger-side pilot delay. They support delayed 6 A startup, but do not establish the charger's internal mechanism or exclude influence from repeated resume commands. A single-resume long observation is still outstanding.

Core admission delay reproduced in software

Source review found that recordEVOffers uses the driver's declared power freshness interval as a command-settling interval. Easee declares power_max_age_s=180. Recent command rises can therefore remain reserved as potentially unobserved load after a zero-power pause. The admission calculation combines that reservation with measured/thermal phase loading and a 35-second restart dwell.

A controlled test using the released source's existing evMeterSite fixture reproduced a long admission delay. Physical application delay was 5 s, telemetry delay 10 s and house load 900 W in both cases. Sequence: 25 s at a 10350 W request, 25 s pause, then 4140 W request.

Only changed parameter Restart admission wait
Declared power max age 180 s 167 s / 2 min 47 s
Declared power max age 15 s 12 s

Both simulations reached a 4140 W offer; pre-start measured phases were approximately 1.30 A. This demonstrates sensitivity to the freshness/settling coupling and closely explains the long field admission delay, but is not an exact tick-level household replay. The restart dwell may accrue during the pause, so it is not necessarily an additional 35 s after the request.

No production timeout was shortened. Review separate telemetry-validity and command-propagation semantics. Any correction needs protection against delayed execution, stale/silent meters, rebound and multiple chargers; command acknowledgement alone must not release reserved headroom.

Feedback inconsistency relevant to #1762

The owner's FTW screenshot at 03:37:34 shows:

  • “Not following” and “The charger has not said why”;
  • simultaneously “Waiting for the car to start drawing” and “limited by charger max current”;
  • “Continues until the car stops drawing” although delivery had not begun.

This screenshot predates the 03:40:09 pilot transition and is consistent with the measured waiting period. It is not evidence of stale app rendering after startup. The reported current-limit reason is an observation, not a proven explanation of the delay. Review contradictory messaging and distinguish waiting, observed limits and confirmed cause.

Remaining acceptance

  1. Safety regressions before changing Core's freshness/settling coupling, then hardware pause/restart validation.
  2. Single-resume 6 A start to separate retry effects from charger delay.
  3. Full EV priority/backoff/recovery with realized 15 A delivery; investigate later power/pilot shortfalls.
  4. Repeated import-limit cycles, load steps and hour-boundary/budget-exhaustion scenarios (EV charging cycles to zero under import ceiling despite low phase currents #1674).
  5. Real export/daylight phase-current verification (fix(control): phase current takes its direction from the phase's power #1782).
  6. Stale-plan startup ordering (EV briefly resumes on Core startup before restored plan is rejected as stale #1718): separately reproduced on this version; after a correction, repeat restart acceptance.
  7. Consistent status wording and transition timing.

Evidence retained locally: source-timestamped JSONL captures, Core/driver logs, plans and per-test reports. Approximately 3-second capture intervals and asynchronous vendor/site observations cannot exclude faster transients; unchanged vendor values are not independent new measurements. No recorded phase current exceeded 25 A in the cited runs. The controlled replay and field observations are separate evidence, not a complete hardware safety proof.

frahlg added a commit that referenced this pull request Oct 22, 2026
…it (#1793)

#1776 counts an EV order as flowing until the charger can have applied
it, using the highest order sent within the charger's response time.
That included orders a later cut had already replaced. With Easee
Cloud's declared 180 s, a charge at 10,350 W, a 25 s pause and a
4,140 W request kept 10,350 W reserved: the restart waited 2 min 47 s
with fuse_limit while the phases read about 1.3 A. Reported on a real
Easee/Pixii site by segran2 in #1763, reproduced in evMeterSite.

The charger follows its latest order, and the meter shows its draw
until a cut lands, so a cut ends the reservation of the higher orders
before it. A run of rises still counts its highest, which is its
latest, so stacked rises stay covered. The restart now comes after
12 s.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
frahlg added a commit that referenced this pull request Oct 22, 2026
…otection (#1800)

* test(control): field matrix for EV charging and fuse protection

v0.155.0-beta.1 passed our tests and failed on field sites the same
night. We tested our defaults: fixed 3p, no step table, planned charging
stubbed, and chargers that applied an order at once or exactly when they
declared. Easee Cloud applies in 30-60 s and declares 180 s.

TestSiteSimFieldMatrix runs Core's EV charging and fuse protection in the
closed loop against 314 cases: the field reports (the help report of
22 Oct, the site in #1763, the home box) with every charger timing,
a sweep over fuse, phase mode, step table, car phases and house load, and
a timing sweep over every request. Planned charging now runs through the
real controller: a minimal planner sends the slot's Wh and on-power, from
the steps main.go gives the planner.

Each case runs in a synctest bubble, so command evidence, the API's
verdict and live Home use run on the plant's clock. Invariants, every
second: the fuse holds; FTW's limit as before; no fuse cut while every
phase is under the limit; no second cut while an unapplied cut covers the
overage; a planned charge delivers 90 % of what the fuse allows; planned
charging and Charge now never put a three-phase charger on one phase; a
charger drawing against its order reads not following; Home use stays
measured while every device reads.

testdata/sitesim_field_known.txt lists the rows that fail on master and
the fix that turns each green. The sim gains the Easee driver's auto
split and phase hold, and outside steps no longer count as our raise.
The matrix skips -race builds: it finds nothing there and runs 15 times
slower.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(control): the write mode logs what it would fail

* test(control): probe rows from the three-phase review

Twenty-four rows from #1799's review and fix D: a charger whose
table holds only one-phase levels (max 5,520 W, auto), phase mode unset
with a goal and a 2,300 W plan slot, surplus-only with a goal and 2.5 kW
of export, a held 1p order raised to 3p beside a phase at 20 A, the help
report's site with a one-phase car, and a long L1 step under a
three-phase car.

Surplus cases get the planner's PV forecast as pickSurplusSteps reads it,
so the one-phase rule is judged as Core makes it: one phase only when the
next 30 min stay below three phases at 6 A. Surplus cuts follow the
export and are no longer judged as fuse cuts. The trace also logs a
change of reason.

New label hold3p: the app sends Charge now as 3p for an auto loadpoint,
and a charger whose table stops below 4,140 W gets 0 W.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

segran2 commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Latest follow-up — 22 October 2026: single-resume 6 A hardware test

Result: the approximately five-minute startup delay also occurs with only one Core-issued resume. This updates the earlier outstanding single-resume test. It does not validate this PR's allocation change.

A temporary, locally built Core diagnostic based on released v0.155.0-beta.1 used the local slot label v0.155.0-beta.9001 (not an official release). Original local Easee driver 1.3.12 was retained. A positive manual hold could enable diagnostic_single_resume only for a bounded duration of at most 600 seconds. Suppression happened in Core's recovery scheduler, not through failed/fabricated driver acknowledgements. Fuse/load-protection timing, admission clamps, stop and fault handling were unchanged.

All times Europe/Stockholm:

  • After an explicit pause, verified 0 W and a zero-power command before arming 4140 W / three-phase diagnostic hold.
  • Normal fuse protection initially withheld admission; this is separate from the following charger response interval.
  • 16:29:23.606: the single ev_resume was acknowledged.
  • 16:29:28.914: intended 6 A limit reasserted; this is a current write, not another resume.
  • 16:34:26: first positive pilot source timestamp, 6 A — about 5 min 2.4 s after resume.
  • 16:34:33.313: first captured positive EV power, approximately 194 W during ramp-up.
  • By 16:35:05: approximately 4186 W delivered. Site import/phase measurements supported physical delivery.
  • No subsequent resume acknowledgement or diagnostic-refusal error occurred in the captured test interval.

Interpretation: repeated Core resume attempts are not necessary for the five-minute delay to occur. The result supports a delay beyond Core admission, but does not establish the internal Easee firmware/cloud mechanism, exclude all vehicle interaction, or eliminate every current-reassertion effect. One controlled run is not universal startup acceptance.

Software validation before deployment: control, loadpoint, telemetry and API suites passed; targeted loadpoint/API race tests passed. Tests covered a single attempt, suppression after an uncertain failed attempt, automatic return to ordinary recovery after expiry, bounded API validation and visibility, and retained zero-power/manual-stop dispatch.

Earlier failed method remains excluded: the Lua duplicate-refusal experiment caused Core's normal driver-fault escalation and return to autonomous default. That run cannot answer the startup-delay question. The FTW screenshot at 04:17:27 showed this induced command failure, not a confirmed Easee hardware fault. The “charger reports a fault” wording warrants separate feedback review (#1762).

Restoration verified: native launcher rollback restored original Core v0.155.0-beta.1 and its exact original binary checksum; original Easee 1.3.12 checksum also matched. Temporary hold removed (manual_active=false), ordinary plan/deadline control resumed and fallback rollback timer disabled. No protection waiting times were changed. Installation/restart transitions are excluded from the actual paused-start test.

Evidence retained locally: source-timestamped JSONL capture, driver logs, diagnostic code/tests and hardware-run report. Approximately three-second sampling and asynchronous sources limit transient/timing conclusions. Full EV/Pixii priority, stable requested-current delivery, import-limit edge cases and export-phase acceptance remain open.

segran2 commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Retest on released v0.155.1-beta.1 — 22 October 2026

Follow-up to the single-resume investigation. Both this PR and #1762 remain unmerged; these are observations of the released version, not hardware acceptance of either PR head. Local Easee driver 1.3.12 retained; EV charge cost web-only patch installed. No Core diagnostic mode active. All times Europe/Stockholm.

Pause/restart admission improved in this run

  • 7 A start succeeded, approximately 4771 W; pilot source timestamp 16:47:16.
  • Explicit pause verified 0 W / zero command at 16:48:32.407; requested 4140 W / 6 A immediately afterward.
  • First resume acknowledgement 16:48:44.161, approximately 11.8 seconds after the request. The former roughly three-minute Core admission delay did not recur in this scenario.
  • The released reservation correction is distinct from blindly shortening declared command delays: our earlier blanket-shortening experiment failed simulated delayed/multiple/single-phase safety tests at 27–31 A. That rejected experiment must not be presented as the released implementation. No protection times/settings were modified during this hardware retest.

Easee delay remains

  • Normal Core recovery repeated resume at 16:49:14 and 16:49:49; no-charge warning at 16:50:18.
  • Positive 6 A pilot source timestamp 16:54:31, about 5 min 46.8 s after first resume; delivery then approximately 4147 W.
  • Together with the earlier one-resume run (16:29:23.606 resume, 16:34:26 pilot, approximately 4186 W), this separates the residual delay from Core admission and shows repeated resume is not necessary for it to occur. Firmware/cloud/vehicle mechanism remains unproven; current reassertions were not eliminated.

Short 7500 W import-ceiling retest

  • At approximately 16:55:19 requested 10350 W with a temporary 7500 W hourly-average import ceiling.
  • Core limited EV offer to 7590 W, reason import_limit; delivered approximately 7539 W while Pixii discharged approximately 1 kW.
  • Recorded maximum grid import 7529 W, maximum absolute phase 11.71 A; no sampled positive-to-zero cycling.
  • The 29 W instantaneous excursion above 7500 W is not itself a failure of an hourly-average ceiling.
  • Short, roughly three-minute scenario only: no hour boundary, exhausted budget, forced house-load step or ignored-command acceptance demonstrated.

Outstanding allocation acceptance
Pixii was approximately 89.5% SoC at baseline. There was insufficient charge margin for a meaningful battery-first backoff test, so full requested-current EV priority over optional Pixii charging remains unverified. Battery discharge during the import test is not simultaneous battery-charge acceptance or a daytime solar-export test.

Removed the test hold and restored the import ceiling to its prior disabled value; final readback: v0.155.1-beta.1, manual_active=false, commanded_reason=plan, EV 0 W. A separate cap-restoration watchdog was armed as a fallback. No driver, persistent goal or fuse/load-protection setting changed.

Support evidence prepared: a standalone Swedish report consolidates four timed direct-6-A runs, 7 A-to-6 A comparisons, source/receipt timestamp limits and specific questions for Easee. Exact model/firmware still need verification; no claim of a confirmed internal firmware cause. The document has not been sent to Easee. Raw captures and report retained locally; no credentials included here.

See the companion feedback update in #1762. Keep remaining acceptance open.

segran2 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Hardware follow-up — 23 October 2026: reservation candidate and Easee allocation trace

Partial acceptance only. The local candidate keeps the EV command at 15 A while limiting optional Pixii charging, but the latest trace reproduces a separate fall in Easee's own allocated current and pilot. This is not complete end-to-end acceptance or validation of the unchanged PR head.

Environment and source scope: local ARM64 Core slot v0.155.1-beta.9002, based on released v0.155.1-beta.1 plus this PR's 387b7d7 reservation change and additional local transition corrections. Those follow-ups retain the reservation during a pending EV pause, account for pending battery import increases and preserve only already-commanded, still-permitted battery discharge relief until its release is covered by measured headroom. These additional source changes are local and are not in this PR head. They must be reviewed and committed separately before the candidate can be equated with this PR. Original local Easee 1.3.12 was used, with temporary diagnostic instrumentation in the final run. EV charge-cost changes remain web-only. No fuse/load-protection waiting times or site fuse settings were changed.

Candidate software checks: full make verify and focused race tests passed locally; Docker-context validation was skipped because no daemon was available. The 340-case replay found no remaining own-raise safety violations after the local corrections, but 23 pre-existing known idle failures remain covered by the existing expectation map. This is not an all-scenarios acceptance claim.

All following times are 23 October, Europe/Stockholm:

Run Observed result Maximum measured phase
00:56–01:02, battery-first EV reached 13 A; test aborted at a 25.33 A L1 sample. L1 jumped about 4.71 A while other phases and EV were nearly unchanged; a house-load step is an inference, not an identified appliance. Core had already reduced the battery target from about 4.9 kW to 639 W before test cleanup. 25.33 A
01:12–01:22, 1.5 kW battery Core held a 15 A EV command for about eight minutes. Pilot reached 15 A and EV about 10.39 kW with Pixii about 1.53 kW; no unexpected stop. 18.95 A
01:36–01:44, stepped battery EV initially delivered about 10.37 kW during 1.5/3 kW battery requests. With 6 kW requested, Core limited Pixii to about 5 kW and retained the 15 A EV command; Easee pilot fell 15 → 14 → 12 A and EV to about 8.23 kW. 23.74 A
01:53–02:02, repeated steps with allocation/command trace The reduction recurred, now with direct allocation evidence described below. All battery steps completed; no unexpected EV stop. 24.13 A

The first run's 25.33 A sample must remain part of the safety record; successful later runs do not erase it or exclude faster unsampled transients. In the 01:36 run, the conditional full-EV projection reached about 24.70 A; this was an asynchronous projection, not an actual measured phase current or proof that the 24 A working margin always held.

New localization: allocated current falls before/with the pilot

The final run added circuit allocation observations 70–72, temperature and related limits to the normal Easee observation request, and recorded every outgoing driver command/settings POST with safe numeric payload fields.

  • 01:54:22: all three allocated phase currents and pilot were 12 A, although Core/dynamic-current readback were 15 A and Pixii was at 0 W.
  • 01:55:14: allocation and pilot rose to 15 A, 52 seconds later, without a changed Core request.
  • Battery requests then stepped through 1.5 and 3 kW, and 6 kW from 01:58:48.847.
  • 02:00:21: allocation and pilot fell together to 14 A.
  • 02:00:32: allocation and pilot fell together to 13 A, with subsequent EV delivery about 8.85 kW. Core command and dynamic-current readback remained 15 A.
  • The command trace contains continuous sequence numbers 1–120, all transport-successful. After startup and before cleanup, there were no FTW driver pause, zero/lower-current or phase-setting commands; 15 A writes continued across the reduction. Startup itself included two resume calls with current reassertions. HTTP success is not proof of firmware application, and this trace does not audit other external controllers.
  • Fresh reported maximum temperatures were 32–34 °C. No positive thermal-derating evidence was captured, but individual sensors/derated-current were unavailable. Reported static charger/circuit maxima were 16 A, circuit dynamic limits 40 A, smart charging false. Several of these are old last-change observations; timestamps alone are not communication-failure evidence.
  • Reason 77 was timestamped 01:56:25, before the reductions, so it does not uniquely establish their cause. Equalizer details and load-balancing peer count were unavailable.

Interpretation: this is more specific than a power-only mismatch: Easee reported a lower circuit allocation and advertised pilot despite a 15 A FTW request. Car-only refusal to consume the offered power does not explain the lower advertised pilot by itself. The underlying Easee/site allocation decision, another controller, firmware and charger/vehicle interaction are not yet separated. A confirmed firmware defect is not established. The startup 12 A limit also shows that simultaneous Pixii charging is not necessary for every instance of reduced allocation.

Cleanup: both manual test holds were released at 02:01:49.799–.800. Original Easee Lua was restored byte-for-byte; health was ok with four drivers ok. The ordinary plan subsequently requested 10.35 kW EV charging, actual about 8.87 kW, battery 0 W; manual holds were inactive. Therefore cleanup returned to ordinary plan charging, not necessarily idle. Local Core candidate remains installed.

Evidence limits / remaining work: raw JSONL site/EV measurements, vendor source timestamps, allocation fields and complete command trace are retained locally. Sources are asynchronous and unchanged vendor values are not independent physical samples. Internal reservation before/after values were not instrumented, so observed battery limits do not isolate this clamp from all other Core clamps. Review/publish the local source follow-ups separately; retain full hardware acceptance as open; request Easee allocation/site-control audit for 00:00:21Z and 00:00:32Z on 23 October. Firmware observation: 344. This run does not retest the separate direct-6-A delay.

Companion feedback implications are recorded in #1762. Neither PR should be closed or treated as fully hardware-accepted on this evidence.

segran2 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Comparison with #1789 — 23 October 2026

CI for this PR's 4372354 has completed: every executed check passed; conditional jobs remain explicitly skipped.

Compared that head with #1789 at c60da23, using the same input test file and small adapters for the replaced allocation function/history layout. Production code was unchanged. Nine inputs were evaluated both at allocation and through complete ComputeDispatch; four zero-target inputs also ran in ordinary ModeIdle: 22 decisions per branch.

Separate the policy difference from the pending-battery regression:

Input #1763 battery target #1789 battery target
Stable 15 A offer, only 4,175 W EV delivery, battery previously 6 kW 280.4 W 6,000 W
Full 10,350 W EV delivery 6,000 W 6,000 W
Managed EV pause, battery asks to rise 4,140 W 4,140 W
Ending existing discharge with limited phase room −1,400 W −1,400 W
Prior discharge reduction not yet measured; next target zero −827 W 0 W
Same prior reduction now measured 0 W 0 W
Pending positive battery charging increase 3,760 W 3,760 W

The first row is the documented reservation-policy disagreement. The highlighted row is different and uses full EV delivery:

  1. Fresh meter phases 22.3 / 12.3 / 12.3 A, total 10,787 W; battery actually −2,000 W; EV demand/offer/delivery all 10,350 W.
  2. Battery command history: −2,000 W in force for an hour, then −1,000 W sent two seconds ago, still not reflected by the fresh meter/battery readings.
  3. Next battery target 0 W. Thus 1,000 W import increase is already pending, and ending the remaining discharge would add another 1,000 W.
  4. On the 25 A/230 V/3-phase site with 1 A margin, remaining room is (24−22.3)×690 = 1,173 W.
  5. fix(control): reserve EV demand until offered power is delivered #1763 retains −827 W, projecting 24.000 A after the target arrives.
  6. fix(control): fuse protection as one function #1789 permits 0 W, projecting 25.19855 A after the target arrives.

The new invariant assertion fails on #1789 at allocation, complete manual dispatch and ordinary idle dispatch; it passes on #1763. Healthy drivers, battery SoC 50%, charge/discharge caps 10/5 kW and fresh aligned readings were used. The complete-dispatch fixtures disable the separate slew limiter and dispatch interval so this tests the fuse clamp's own admission decision. This is a conditional balanced-response calculation with unchanged house/EV loads, not measured hardware overcurrent, fuse operation or proof of the duration of an excursion. A configured slew limiter and subsequent correction can change the physical trajectory.

Code inspection is consistent with the result: #1789 subtracts pending battery import from room for positive charging increases, while its existing-discharge retention calculation does not subtract that pending import. #1763's follow-up accounts for it when releasing relief as well.

The selected existing #1789 scenario/phase/relief/battery-fuse tests pass. Its different simulator version was not presented as an identical run of the 340-case matrix. No #1789 code was modified, no hardware commands were issued and the physical FTW remains on restored official v0.155.1-beta.1.

Recommendation: carry this pending-import regression into the selected implementation and resolve it separately from the EV-under-delivery reservation policy. This does not require merging all of #1763 into #1789. Keep the policy/integration decision open; the comparison alone is not authority to close either PR.

Exact common test, adapters and raw result logs are retained locally. Common test SHA-256: 69a545b5bbcab142e7dcdf51786341bb731b312f5bd01682324e9e67c4d130d8. Temporary test files were removed from both clean checkouts after capture.

segran2 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

The independent pending-battery regression identified in the comparison is now addressed in #1816, stacked directly on #1789 (fix/fuse-one-function). It changes only the relief shortfall calculation, adds import/export regressions through allocation/manual/idle dispatch, and preserves #1789's EV-reservation policy. On commit c2246d1, make verify, full control/telemetry/loadpoint race tests and the telemetry-read ratchet pass; Docker-dependent checks were skipped. No existing golden records or failure exemptions were changed. The new PR remains draft; neither #1789 nor #1763 was merged or closed, and the installed FTW remains unchanged.

Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.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.

2 participants