Repository navigation
Conversation
An Easee charger's load balancer can cut the car below FTW's request. The EV sheet then said "Not following" and that the charger had not said why, with requested current, charger offer and charger limit all equal. Read the driver's vendor-neutral current_limited_by. When it names the load balancer and the car draws less than asked, report load_balancer_limit as limited, with words that name the load balancer. More power than asked still warns. Move the bundled driver pin to srcfl/device-drivers#172, which keeps the load-balancing reason while the car charges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
This was referenced Oct 8, 2026
11 tasks done
3 of 5 tasks
This was referenced Oct 18, 2026
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
This was referenced Oct 21, 2026
#1537 (602aa0f, e33726b) on current master, as Segran integrated it in #1823 (e225339): the feedback code keeps master's one-phase and hourly-import paths beside the load-balancer reason. The driver pin from both PRs is left out; it moves only to a merged driver commit. Co-authored-by: Segran <goran@andersson-stehag.se> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Göran's trace (#1763, 23 Oct 2026): FTW ordered 15 A throughout, the charger read back 15 A, while Easee's own load balancing signalled 12, 14 and 13 A to the car. FTW said "Not following". easee_cloud 1.4.1 reports current_limit_a while the charger's offer to the car is below the order, and current_limited_by = "load_balancer" when Easee's allocation shows the cause. Core reads both. Once the order has stood its response time and the car takes about that limit, the verdict is limited/load_balancer_limit (info), or offered_current_lower (warning) when no cause is shown. A car taking far less than the limit, nothing, or more than asked keeps its not-following verdict. The row carries limit_a, limited_by and the charger's make, so the sheet says "Easee limits the charger to 13 A (its load balancing). FTW asked for 15 A; the car takes 8.8 kW." and the numbers list the allocated current beside requested and offered. This replaces #1537's reason-only branch, which also called a car at zero limited. The field matrix gains Göran's charger as two probe rows; its Charge now row fails on master with not_following. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
The two commits below, e06b728 and 5c2f2ec, are #1537 on master 286ac14 as Segran integrated it in #1823, then the rework for easee_cloud 1.4.1. This merge keeps the branch's earlier history instead of rewriting it; its tree is the rebased tree. The driver pin returns to master's: it moves only to a merged driver commit. Co-authored-by: Segran <goran@andersson-stehag.se> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes to the load-balancer verdict: - Check the order the charger holds (max_a) before the driver's lower current, so a charger holding 12 A of a 15 A order still reads offered_current_lower. - A car taking more than the limit allows is not limited by it. - Allow 2 A below the limit as well as 10 %, so a balancer stepping up from 12 to 14 A does not flash "Not following" while the cloud still reports the car's old draw. - Require a positive limit; clear make with the other stale fields. - Words: "Load balancing allows 13 A" and "The charger lets the car take 13 A" for the driver's current, so a card never says the charger offers both 13 A and 15 A. - The field matrix's balancer rows send max_a like the driver. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
- The margin below the limit is 10 %, or as the car follows a step up to 2 A but at most 15 % of the limit, so a car with its own cap well under a low limit stays not following. - When the charger holds a lower order and the driver also reports a lower current, the sentence names the held order. - Tests for the positive-limit guard without a readback, for stale rows dropping limit, cause and make, and for both margin edges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Göran (@segran2) traced an Easee Home on 23 October 2026 with every FTW driver POST logged (#1763 comment, #1762 comment). FTW ordered 15 A throughout and the charger read back 15 A. Easee's own circuit allocation and the current it signalled to the car fell to 12 A at the start, then 14 A and 13 A while the home battery charged. The car took 8.2–8.9 kW instead of 10.4 kW. FTW sent no lower order, yet the EV sheet said "Not following … The charger has not said why".
Change
This PR now carries four things:
current_limit_a, the current the charger signals to the car while it is below the order the charger holds and answers that order, andcurrent_limited_by = "load_balancer"only when Easee's allocation shows the cause. Core:limit_a,limited_byand the charger's make (from the driver's reported identity) on the control row;max_a), and the car takes about that limit (within 10 % below it, or as the car follows a step up to 2 A but at most 15 % of the limit; never above), sayslimited/load_balancer_limit(info), orlimited/offered_current_lower(warning) when no cause is shown. A charger holding a lower order than FTW sent still readsoffered_current_lowerfrommax_afirst;makecleared with other stale fields, and words that never say the charger offers both 13 A and 15 A; a lower held order is named before the driver's current.The EV sheet now reads:
Without a make: "The charger’s load balancing limits it to 13 A. …". Numbers list "Requested current 15 A", "Charger offer 15 A" (the order the charger holds), "Charger limit 16 A" and "Load balancing allows 13 A"; "Measured" shows what the car takes. With no shown cause the sentence reads "The charger lets the car take 13 A, below the 15 A FTW asked for."
Evidence
Each test failed first on the code before it:
TestEaseeLoadBalancingReadsAsLimitedreplays Göran's case throughcontrolFeedback, with the charger reading back 15 A: a named 13 A limit with the car at 8,850 W readslimited/load_balancer_limit/infoand is never "not following" on the way; the limit without a cause,offered_current_lower; no limit,power_below_target; the car at 0 W,no_power_response; at 4 kW,power_below_target; at 7.5 kW (2.1 A under the limit),power_below_target; at 3.8 kW under a 7 A limit,power_below_target; at 10.3 kW (the order),following; a limit at the order,power_below_target; a zero limit, with or without a readback,no_power_response; a charger holding 12 A,offered_current_lower. On fix(control): say Easee limits the charger to N A, not "Not following" #1537's code five of the first six cases fail; "car at the order" and "charger holds 12 A" also fail on 5c2f2ec, before the review fixes.TestEaseeLoadBalancingStepsUp: the balancer steps from 12 to 14 A while the cloud still reports the car at 8,280 W; the verdict staysload_balancer_limit. It fails on 5c2f2ec withnot_following/power_below_target.TestChargerLimitCarriesTheMake: a row with a limit carries the make "Easee" from a real driver registry; a row without does not, and a stale row drops limit, cause and make. It fails on fix(control): say Easee limits the charger to N A, not "Not following" #1537's code.pr1763/…/planned+balancer18A,…/chargenow+balancer18A): Easee keeps each phase under 18 A after the house, so the car gets 12 A of a 15 A order, and the sim's adapter reports it as the driver does. The adapter sendsmax_aand the limit for these rows as the driver does. The verdict check now demandsload_balancer_limitwhile the car is held at the reported limit (both verdicts pass in the first 30 s after the limit moves). On master's Core the Charge now row fails:the car draws 8280 W against an expected 10350 W (5m30s), the verdict says not_following/power_below_target. 344 cases, none fail. The existing pr1763 rows still model a car that holds itself at 8.3 kW; their comment now says the trace showed Easee did it on that site.web/control-feedback.test.mjschecks the words, both make cases, the numbers, the unexplained case and a charger holding a lower order.npm test: 886 passed.make verifypassed exceptinternal/drivers(the worktree's generated driver snapshot was stale; passes aftermake drivers) andTestLiveBackupPastItsLimitNamesTheLimitAndTable(a 1 s backup time limit hit under load; passes on rerun). Both pass on rerun.web/CSS and module in headless Chrome at phone width, for the named, unnamed and no-cause rows. A human still needs to look at it in the real EV sheet, and nobody has seen this with a load-balanced Easee yet.When Easee releases the car, the driver keeps the last limit for up to 20 s while the car still draws below the order, so the sheet does not flash "Not following" before the cloud reports the new draw.
Found on the way, not fixed here: if Easee's load balancing counts the home battery and sits below FTW's fuse setting, it can stop the car while FTW charges the battery (in the sim the car sat idle for 2 h and got 5.3 of 9.9 kWh). That is EV priority over battery charging (#1763, #1789).
Pairing and order
web/control-feedback.jsand needs a fresh copy; until then the app shows "The box reports “load_balancer_limit”, which this version cannot describe."drivers/BUNDLED_SOURCE.jsonto feat(ci): attach rpi-image PR builds as draft preview releases #194's merge commit.#1823 stays open for its author; this PR took in its integration.
🤖 Generated with Claude Code