Repository navigation
feat(cloud): the car class in FTW Cloud's copy, and a charger's level and goal read from its car - #1662
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9aa7315707
ℹ️ 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".
| // The session names the plug-in the tap answers. The cars go | ||
| // with the event to FTW Cloud once the uplink cuts their | ||
| // opaque ids (docs/cars.md). | ||
| go s.handleCatalogued(PushCarWhich, ev.LoadpointID, map[string]string{"session": ev.Session}) |
There was a problem hiding this comment.
Carry the car choices into car.which notifications
When an ambiguous session has two to four eligible cars, this drops ev.CarIDs and forwards only the session. Neither notifications.Message nor cloudlink.EventIn later reconstructs them, so projectEvent always leaves cloudwire.Event.Cars empty and the phone cannot render the promised one-button-per-car choice. Preserve the IDs through the notification message and project them to opaque car IDs in the cloud event.
AGENTS.md reference: AGENTS.md:L24-L25
Useful? React with 👍 / 👎.
| if lp.VehicleCapacityWh != prev.VehicleCapacityWh && lp.VehicleCapacityWh > 0 { | ||
| c.CapacityWh = &lp.VehicleCapacityWh | ||
| } | ||
| if plugin, prevPlugin := pluginFraction(lp), pluginFraction(prev); plugin != prevPlugin && plugin > 0 { | ||
| c.PluginSoC = &plugin |
There was a problem hiding this comment.
Propagate clearing legacy loadpoint settings
When an operator removes vehicle_capacity_wh or plugin_soc from config (so the new value is zero), these > 0 guards suppress the reload change. The migrated car therefore retains the old persisted capacity or plug-in SoC and immediately reapplies it to the loadpoint, so hidden state continues steering charging despite the setting being cleared. Zero-valued transitions need to clear the corresponding car field rather than being ignored.
AGENTS.md reference: AGENTS.md:L20-L21
Useful? React with 👍 / 👎.
… and goal read from its car The link sends the car class under ftw.live.read when a site keeps cars: each car's level and goal by the grant's opaque id, with nothing that names the car, at most once per lp's period, in full every 15 minutes and after a resync. The change test counts energy and an estimated level with lp's deadbands. A charger whose session has a known car takes its level, source, goal, recurrence and surplus choice from the car's own view, so the two classes agree where a phone joins carId to the car. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9aa7315 to
e0bfe39
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
FTW Cloud's copy carries the cars, as
docs/protocol-cloud.mddefines since #1647. The service half is srcfl/ftw-cloud#23 and the phone half srcfl/ftw-app#77.Built on #1650, now merged; this is one commit on master.
carclass. When the site keeps cars (cloudlink.CarSite, whichcmd/ftw'scloudSitemeets with the car runtime), the link sendscarunderftw.live.read: each car's level and goal by the grant's opaque id, through feat(cars): the car apart from the charger, in Core #1650'sProjectCars, so no name, maker, VIN, identifier or source leaves the box. It goes at most once perlp's period, in full every 15 minutes and after aresync, andhello.capsnames it. A site without cars sends none, so the test fakes in other packages are untouched.socAgeSand countsenergySinceWhat 100 Wh, as the document says, and the level at 10 ‰, aslpcounts its level. Without that band an estimated level that rises with a charging car would send the class at nearly every reading. Whether the level is an estimate counts at once. The document now says so.socPermilleas the car's;socSourcevehicle(with itssocAgeS),assumed,unknownorinferred;targetPermilleandrecurringfrom the goal;surplusOnlyas the car's.readyByMsstays the box's next ready time for that goal. Before this, within the first kWh after someone set the level, the charger showed the reading plus the energy since, with an emptysocSource, while the car class showed the reading. The agent reads (loadpoints.get) use the same view.lp.carIdwas already filled by feat(cars): the car apart from the charger, in Core #1650 and cut per grant byProjectLP.Tests
cloudlink: the class goes by an opaque id and names no car; it needsftw.live.read(and the link does not read the cars without it); a goal goes within lp's period while 60 Wh does not; a resync sends it again; the change test's bands.cmd/ftw:TestTheChargerShowsItsCarAsTheCarClassDoesruns the real car runtime and loadpoint manager through a tapped session: no level, a level set with half a kWh since, and an estimate. Without the join the second step fails (charger 431 with no source, car 420 manual).GOFLAGS=-p=2 make verify: clean (vet, tests, build).After master's QUIC (#1653)
Master's merge brought a new seam for the fake service (
afterHellotakes anuplinkConn); 18c268e moves the two car tests to it. Without that the branch no longer builds its tests on master.Deploy order
Cloud first (srcfl/ftw-cloud#23 holds and serves
car), then boxes (this), then phones (srcfl/ftw-app#77). A service from before drops the class, as any unknownt.🤖 Generated with Claude Code