Skip to content

fix(easee_cloud): report a load-balancer limit while the car charges - #172

Draft
frahlg wants to merge 1 commit into
mainfrom
easee-load-balancer-reason
Draft

frahlg wants to merge 1 commit into
mainfrom
easee-load-balancer-reason

Conversation

@frahlg

@frahlg frahlg commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Problem

A tester on FTW v0.140.0-beta.1 (Easee Cloud, Pixii, 25 A three-phase fuse) saw "Asked for 11.0 kW, delivering 8.3 kW. The charger has not said why." The charger's load balancer had cut the car to about 12 A per phase while the battery charged 4.75 kW. FTW's requested current, the charger offer (observation 48) and the charger limit all read 16 A, so none of them showed the cut.

driver_poll drops any ReasonForNoCurrent while the charger reports charging above 100 W and the reason's timestamp is not newer than TotalPower's. Easee records an observation when its value changes. A load-balancing reason set when the limit began is older than the next power change, so the driver dropped it while the limit still held.

Change

  • While charging, keep an old reason if it is a load-balancing code and the per-phase current is at least 2 A below the offer. The offer is observation 48, or FTW's last write when 48 is missing. Every other old reason is still dropped while charging.
  • Emit current_limited_by = "load_balancer" for codes 1–5, 10 and 25–30 while a car is connected. Core reads this vendor-neutral name, not Easee's codes. Codes 77 and 78 are the charger's own limits, which Core already reads as device_limit_a and max_a; the car's codes are not the load balancer either.
  • Match the labels for codes 6, 8–11, 25–30 and 77 to Easee's published table. Code 28 read "fuse limit reached"; Easee calls it "Current limited by Equalizer".
  • Add current_limited_by to the EV keys in spec/host-api-profile.json and to the control feedback section of docs/WRITING-A-DRIVER.md. Add Easee's enumeration page to upstream_docs.
  • Bump easee_cloud 1.3.6 → 1.3.7.

What is confirmed and what is inferred

Confirmed from Easee's docs:

  • Enumerations defines 25–30 as "Current limited by circuit fuse / circuit max current / dynamic circuit current / Equalizer / circuit load balancing / offline settings", and 1–6 as load-balancing reasons for no current. The wording of 25–30 describes a reduced current, not zero. pyeasee uses the same table.
  • Observation 96 is described as "why a charger with a car connected is not offering current to the car".

Confirmed in this driver: the timestamp rule above drops any reason older than the last power change. Earlier hardware work confirmed that Easee keeps an unchanged TotalPower timestamp for minutes (#131).

Inferred, not seen: that Easee sends 25–30 while a car charges, and which code the tester's charger sent. No raw observations were captured from that site, and I have not seen a load-balanced Easee on hardware with this change. The 2 A gap is a judgement: a car may draw a little under the offer, and the per-phase current is derived from total power and one voltage.

Limits

  • The per-phase current uses the driver's committed phase count. A car charging on one phase while the driver holds 3Φ reads a third of its real current, so an old load-balancing reason would be kept. Core still requires a measured shortfall against its own command.
  • Observations 111–113 (dynamic circuit current) and 230–232 (Equalizer available current) would show the clamp directly. The driver does not read them yet; that needs a capture from a site that uses them.

Paired PR

srcfl/ftw#1537 moves the bundled driver pin to this branch's head and makes Core report load_balancer_limit as limited, with words in the UI. Merge this first, then move the FTW pin to the merge commit.

draft #159 also bumps easee_cloud to 1.3.7. It changes driver_command; this PR changes driver_poll. Whichever lands second needs 1.3.8.

Tests

  • drivers/tests/lua_harness/test_easee_cloud_load_balancer.lua with drivers/tests/test_easee_cloud_load_balancer.py: the reported case (16 A offer, 8.3 kW on three phases) keeps code 29 and reports the load balancer; codes 28 and 27 too; a car at the full offer, a gap under 2 A, an old non-balancing reason and an unknown offer drop it; FTW's last write stands in for a missing readback; a car held at zero by codes 2 or 5 is reported; 52, 100 and an unplugged charger are not. The test fails on main at its first assertion.
  • make test-driver ID=easee_cloud: 40 passed, 15 skipped.
  • make check: 4902 passed, 923 skipped.

🤖 Generated with Claude Code

Easee records ReasonForNoCurrent when it changes. The driver dropped any
reason older than the last power change while the car charged, so a
load-balancing limit that began earlier vanished and Core said the
charger had given no reason.

Keep a load-balancing reason while the measured per-phase current stays
at least 2 A below the offer, and tell Core with the vendor-neutral
current_limited_by = "load_balancer". Match the reason labels to
Easee's published table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>

This branch has not been deployed

No deployments
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