Skip to content

feat(easee_cloud): emit request_active so the host can tell car-declined from box-paused - #103

Merged
frahlg merged 1 commit into
mainfrom
easee-request-active
Aug 30, 2026
Merged

feat(easee_cloud): emit request_active so the host can tell car-declined from box-paused#103
frahlg merged 1 commit into
mainfrom
easee-request-active

Conversation

@frahlg

@frahlg frahlg commented Aug 30, 2026

Copy link
Copy Markdown
Member

Why

Field report (srcfl/ftw#1002, 2026-08-29): a car at its own charge limit held Easee reasonForNoCurrent=50 all night while the FTW box kept offering 11 kW and paged the operator twice with spurious charging.interrupted notifications. The host could not tell "the car declined" from "we paused it" because this driver never emits request_active — the field the loadpoint manager's session-completion latch, manual-hold auto-release and interruption suppression all key on. Today only ctek_hybrid emits it.

What

  • Emit request_active in the ev telemetry: false only when the vehicle side has explicitly stopped requesting current — reason 50 ("secondary unit not requesting current"; the vehicle is the secondary unit) or op_mode 4 ("completed"), while connected and not charging. Every box-ordered pause (52/53/100 "dynamic limit too low", pending authorization, schedules, fuse limits) keeps the default true, so a pause we ordered is never mistaken for the car declining. The host debounces 90 s before acting, so a brief 50 during session handshake is harmless.
  • Editing this FTW-promoted driver wakes the full catalog suite, and the driver did not meet its HTTP rules. It now does: every host.http_get / host.json_decode goes through pcall-wrapped safe_http_get / safe_json_decode, so a raising host or a garbage API response degrades to (nil, err) instead of killing the poll.
  • Version: the catalog manifest had already drifted to 1.1.1 while the DRIVER block said 1.0.1. Both now agree on 1.2.0. Manifest sha/size and index.yaml regenerated with the repo tools.

Host-side effect (no host change needed)

request_active=false only ever pauses optimism — it never commands charge. With it, the FTW host's existing logic starts working for Easee: the session-completion latch stops the planner allocating energy to a full car, a manual Start hold auto-releases after 90 s instead of pinning all night, and charging.interrupted stops firing on the car's own ~900 W renegotiation bursts.

Reaching FTW's bundled snapshot needs the usual follow-up there: move the pin in drivers/BUNDLED_SOURCE.json and run scripts/sync-bundled-drivers.sh.

Checks

  • make test-driver ID=easee_cloud — 36 passed
  • make check — 4035 passed, 1309 skipped

🤖 Generated with Claude Code

https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi


Note

Medium Risk
Changes EV loadpoint semantics for all Easee Cloud sites and tightens poll resilience; misclassification of reason 50 vs box pauses could affect planning and notifications, though host debouncing limits blast radius.

Overview
easee_cloud 1.2.0 adds request_active on ev telemetry so the FTW host can distinguish the vehicle stopping its charge request from a pause the charger or controller ordered.

request_active stays true by default and goes false only when the car is connected, not charging, and Easee reports reasonForNoCurrent 50 (secondary unit not requesting current) or op_mode 4 (completed). Box-driven stalls (e.g. 52/53/100, schedules, authorization) keep true, which lets existing host logic (session-completion latch, manual-hold auto-release, charging.interrupted suppression) behave correctly on Easee without host changes.

Poll-path HTTP GET and JSON decode now use pcall-wrapped safe_http_get / safe_json_decode so bad responses or raising bindings fail the poll instead of crashing the driver. Catalog metadata (manifest, index, devices, support status, CHANGELOG) is bumped to 1.2.0 with updated artifact hash/size.

Reviewed by Cursor Bugbot for commit 457cfec. 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:37:25.940299Z 9707f7b 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: 9707f7ba83

ℹ️ 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".

-- its own charge limit held reason 50 all night while the box kept
-- offering 11 kW and paged the operator twice about it.
local request_active = true
if connected and not charging and (reason_code == 50 or op_mode == 4) then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Register the Easee enumeration as upstream documentation

This new interpretation of Easee reason 50 and operation mode 4 depends on vendor-defined enumeration semantics, but manifests/easee_cloud.yaml still has no upstream_docs entry. Because .github/workflows/watch-upstream-docs.yml only watches URLs declared in manifests, changes or removal of the documentation underlying request_active will go unnoticed; add the durable Easee enumeration/API reference to the manifest.

AGENTS.md reference: AGENTS.md:L60-L66

Useful? React with 👍 / 👎.

@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 with no findings that need human review. No reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

frahlg added a commit to srcfl/ftw that referenced this pull request Aug 30, 2026
* feat(ev): say why the charger is (not) charging and when it will

Field report (#1002): a car plugged in against a schedule sits at 0 W
until the cheap slots arrive, the modal looks dead, and the operator
presses Start — which overrides the plan for the whole session. The
grid-plan deferral (deadline past published prices) is worse: it forces
surplus-only semantics with only an INFO log to show for it, so it
reads as a PV-only mode nobody chose.

GET /api/loadpoints now carries the answer: the next planned charge
window (mpc.LoadpointPlanWindows, same MaxPlanAge cutoff as dispatch so
a stale plan promises nothing), the grid-deferral flag, and what the
controller last commanded (commanded_w/commanded_known, so "offering
power the car won't take" is distinguishable from "pausing on
purpose"). The EV modal renders one sentence from those fields,
refreshed every poll: planned window with clock times and kWh, waiting-
for-prices, car-declined with the charger's own reason, paused-by-box,
PV-surplus-only, or the do-nothing default with the three ways out.

Closes nothing on its own — #1002 also wants Start to become a bounded
"charge now" and the Easee driver to emit request_active
(srcfl/device-drivers#103); those land separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi

* fix(web): 24-hour clock in the EV plan strip

Match plan-brief.js's formatClock — the plan UI speaks 24 h regardless
of browser locale; toLocaleTimeString gave 01:00 PM on en-US browsers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ned from box-paused

Easee reason 50 ("secondary unit not requesting current") and op_mode 4
("completed") are the vehicle's side of the conversation; 52/53/100,
pending authorization and schedule states are ours. Emitting the
distinction lets the FTW host's existing 90 s debounce do its job:
the session-completion latch stops the planner allocating energy to a
full car, a manual Start hold auto-releases instead of offering power
all night, and the charging-interrupted notification stops firing on
the car's own renegotiation bursts.

Editing this FTW-promoted driver wakes the full catalog suite, so the
driver now also meets it: every host.http_get and host.json_decode is
pcall-wrapped (safe_http_get / safe_json_decode) so a raising host or
a garbage API response degrades to (nil, err) instead of killing the
poll.

The catalog manifest had already drifted to 1.1.1 while the DRIVER
block said 1.0.1; both now agree on 1.2.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@frahlg
frahlg force-pushed the easee-request-active branch from 9707f7b to 457cfec Compare August 30, 2026 07:55
@frahlg
frahlg merged commit f98d5c5 into main Aug 30, 2026
9 checks passed
@frahlg
frahlg deleted the easee-request-active branch August 30, 2026 07:57
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