Skip to content

Releases: YossiKon/geely-connect

v1.55.0 - the European Geely app, Unlock Frunk, a card that keeps to its own car

Choose a tag to compare

@YossiKon YossiKon released this 23 Oct 21:02

Three days of owner reports. Everything here was asked for, or measured, by someone on the tracker.

🇪🇺 The European Geely app

@Gamezeta's E2 Pro+ uses Geely's new European app, com.geely.global, and this integration signed him in and found no car (#97). That app talks to its own identity and vehicle servers, not the South-East Asian ones the integration knew. @FadeNow, whose E2 in Spain hit the same wall, worked out the European servers and app identity and sent them as a pull request (#100).

The new-app login now has a New-app server region field, and Europe (requires local app keys) uses the European servers. Country alone changes nothing: the default, and every new-app entry you already have, stays on Australia / SEA.

The European app's keys do not ship with the integration. Europe needs your own geely_eu_app_keys.json in Home Assistant's configuration directory, and without one the login stops and says so. European setup has the format. Verified so far: finding the car and reading its status, on one E2 in Spain with the Android app 1.1.1. Remote commands and other European markets are untested.

🚗 Unlock Frunk

On @maknij's South African E2, the usual door request unlocks every door and the boot, and never the frunk. His capture of the car's own app showed the frunk has a request of its own, rlu (#72). @pablomadias sent that request from Home Assistant to his Brazilian EX2 Max, and the frunk popped.

Unlock Frunk sends exactly that request. It is created only on a car whose capability catalogue names a front trunk, as the E2's does; every other car, and any car whose catalogue could not be read, goes without it. Two things are not known yet: whether the EX2 Max's own catalogue names its front trunk (pablomadias's diagnostics will tell), and how the E2 answers the request when it comes from here. On a car without the button, the same request goes out through fire_control:

action: geely_connect.fire_control
data:
  service_id: rlu
  command: start
  params:
    - {key: operation, value: "1"}
    - {key: rlu.target, value: "1"}

The new platform is not included. There, the frunk is mapped (RDU_2, target hood), but nobody has fired it from here yet.

fire_control also takes latest: true, the app's other body shape: a latest flag in place of the scheduling block, the shape of the E2 app's captured frunk request. The EX2 Max's frunk opened without it.

🃏 A card keeps to its own car

@sendelany runs an E5 EM-i and an E2 in one Home Assistant (#102). The E2's card, with prefix: set, showed the E5's combined range as its headline, plus a fuel bar for a car with no tank. For a sensor the E2 doesn't have, such as the fuel level, the card fell back to searching every Geely Connect entity, and found the E5's. The search now stays on the car the prefix belongs to.


Full gate on release: 1091 tests, 0 failed, 0 skipped, coverage 100%.

v1.54.1 - the E2's Scheduled Charging switch reads the right field, and the Thai catches up

Choose a tag to compare

@YossiKon YossiKon released this 20 Oct 18:44

A day after v1.54.0, one correction to it, and the Thai caught up.

🔌 Scheduled Charging on an E2: the switch reads the right field

v1.54.0 said turning Scheduled Charging on from Home Assistant had not been seen to take on the one car that has it. @maknij's next test showed it had been taking all along (#72): plugged in at 58 %, window moved away from the current time, start from Home Assistant, car not charging, which is the schedule honoured. What was wrong was the switch's reading. It read slot 2's timerId, which only the app's own toggle moves to "1"; after a start from here it stays "2", so the switch showed off, and every time change that followed went out as stop and switched the schedule off again.

Across all ten diagnostics files from that car, the app's toggles and Home Assistant's alike, charging or not, chargeSts in the car's status read "1" after every start and "0" after every stop. The switch and both time entities now read that, with timerId kept as the fallback for a car that does not send it. A press shows at once and holds until the next poll. Only cars whose schedule lives in slot 2 are affected; an EX5 reads slot 6 as before.

Still open on that car, in the same thread: the frunk (the app's request is captured, not yet fired from here) and the scheduled trip.

🇹🇭 Thai

@tomzt read the Thai against the English that landed since #70 and sent five wording fixes (#98, #99): the x-vin option now says the token is usually derived at setup, a car's windows are กระจก, the charge chip says what is ready, and the x-vin repair text uses the words the rest of the file and the Rapid heat / Rapid cool buttons already use. Values only, no keys changed.

And

@pablomadias ran v1.54.0 for two nights on the EX2 Max whose 12 V battery went flat on 1.53.0: the car slept through both (#95). The one-wake-per-press change is unchanged here.


Full gate on release: 1060 tests, 0 failed, 0 skipped, coverage 100%.

v1.54.0 - one wake per press, the E2's own requests, hide what your car lacks

Choose a tag to compare

@YossiKon YossiKon released this 19 Oct 06:46

Nine days of owner reports. Everything here was asked for, or measured, by someone on the tracker.

🔋 One press wakes the car once

@pablomadias's EX2 Max had its 12 V battery flat one morning, with the integration polling every five minutes all night (#95). v1.53.0 had a bug on the new Geely platform: a press of Refresh Data, or Sync on the card, waited for a state block that platform never sends, and every poll it waited through woke the car again, until Home Assistant restarted. The wake is now spent on the first poll after a press, on every platform. Nothing else in the polling changed: a parked car is still read from Geely's cloud, and only woken when it has moved.

If you are on 1.53.0 and use Refresh Data or Sync, this is the release to take.

🚗 The E2, in the requests its own app sends

@maknij rooted a phone, proxied the Geely app and posted every request it makes for his South African E2 (#72). Where a car's catalogue speaks the 1.0 scheme, these now go out exactly as the app sends them:

  • Climate: on, off and the setpoint through RCE, in whole degrees from 16 to 28 °C. Confirmed on the car.
  • All Windows and Window Ventilation: through RWS, down with window, up with all, ventilate both ways. Confirmed on the car.
  • Unlock Trunk: RTU, so only the boot releases. The request this sent before unlocked every door on that car. Confirmed.
  • Scheduled Charging: the switch and both time entities read and write slot 2, the slot his car keeps the schedule in, with the body the app sends. The times reach the car. Turning it on from Home Assistant has not yet been seen to take on the one car that has it; that test is running on #72. A time change now goes out with what the switch was last pressed to, for a minute after the press.

The cards no longer lock every control when an E2 runs remote climate: that car reports its engine running for as long as the AC does, and with the park brake on and no speed, that is parked. A driving_lock: false workaround is no longer needed.

🌡️ Battery Temperature Maintenance reads the right field

@dimitur2204 switched the app's toggle off on his Starray EM-i with the weekday schedule armed, and one field in the car's schedule slot moved: bw (#4). The sensor had been reading a flag that means "a one-off trip is armed", which agreed with the toggle on the first car only because that car's trip was a one-off. It now reads bw, keeps its entity, and two sensors sit beside it: Scheduled Trip Weekly and Scheduled Trip One-off. The slot is read on the normal secondary cadence and on a Refresh press. On the new platform and on a 1.0-catalogue car, which do not answer that slot in this shape, none of the three are created. His pull request, #96.

🙈 hide: on the full and top cards

@phrfpeixoto's car has no heated seats and he never presses the trunk button (#92). The full and top cards take hide: with any of the action row's buttons and the climate panel's seat_heating and seat_cooling rows. Per card, empty by default, so nobody else's card changes. The entities stay; disable them in Home Assistant if you like.

type: custom:geely-card
hide: [trunk, seat_heating]

The compact card takes buttons: like the strip and mini since v1.53.0, and maps, waze, apple and here can be among them as links to the car's position (#87).

🔔 Charging countdown, and the rest

  • The charging countdown notification could keep ticking on the lock screen for hours after an early unplug. @shanehughes-ui's #93 clears the ongoing one before posting the stop summary, which now sounds once if the countdown channel does.
  • The country list at setup is alphabetical, so Australia sits beside Austria (#94).
  • set_scheduled_trip refuses to re-arm a departure already in the past (#4), and sends a bw of 0 back as 0.
  • Bulgarian, for the setup flow and the cards (#90, #91), and the new-platform setup and x-vin repair in every language.
  • The README lists the EX2 and what it does differently.

Full gate on release: 1058 tests, 0 failed, 0 skipped, coverage 100%.

v1.53.0 - the buttons you choose, an E2 told apart, a scheduled trip service

Choose a tag to compare

@YossiKon YossiKon released this 10 Oct 20:16

Four weeks of owner reports. Everything here was asked for, or measured, by someone on the tracker.

🎛️ Choose the buttons on the strip and mini cards

@lindsaymarkward unlocks the car and stops the charge every morning, and the strip's five fixed buttons included two he never presses. buttons: now picks which icon buttons are drawn, in order:

type: custom:geely-card-strip
buttons: [lock, charging]

The names are lock (follows the car - Lock or Unlock), heat, cool, trunk, find, charging, climate and refresh. charging reads Stop charging while the car charges and Start charging otherwise, and only appears on a car that has the Charging switch. Leave buttons: out and both cards draw exactly what they did before (#83).

🖼️ Your own car photo, lit like the drawing

@nikolajhendel set car_image and found three differences from the drawn car (#85). The charge port now holds a steady light while charging instead of pulsing, and the photo stands on the drawing's shadow, which takes the accent colour while charging.

The red mark he saw on the bonnet is most likely the tail lamp's park-brake glow. The overlay positions were measured on a car facing left, so on a photo facing right every spot lands mirrored. car_image_facing: right now flips them. Positions you set yourself in car_image_hotspots are used as given, and a new ground spot places the shadow.

🚗 The E2, and other cars on the 1.0 catalogue

@maknij went through every control on his South African E2 against the official app, and @sibero80's Colombian E2 matched it (#72). These cars describe their features in an older scheme, and several controls here did nothing on them. Where the car's own catalogue says so, they are no longer created:

  • The Charging and Scheduled charging switches, and the two schedule time entities. The app has no start/stop on that car, and its schedule lives in a different slot from the one this integration writes.
  • Parking Comfort. The app has no such option on that car, and a start sent from here sat unexecuted at the gateway for minutes.

The rule only acts on positive evidence: a catalogue that names a 1.0 row and not the 2.0 one. Two real EX5 catalogues keep every control, and a car whose catalogue names neither keeps them too. If you already had these entities on an E2, they'll stay in the list as unavailable after the upgrade, and you can delete them there.

Two readings changed as well. The sunroof reads unknown when the car marks the field invalid, instead of Closed on a roof that isn't there. And Driver seatbelt now has the safety class, so it reads Safe/Unsafe instead of a bare On/Off: an E2 owner buckled, polled and unbuckled, and true is the belt released. The state underneath is unchanged, so automations keep working.

Climate and window ventilation still do nothing on the E2: the car accepts the request and ignores it. That waits on a capture of the app's own request.

🔑 New platform: when the x-vin can't be derived, it says so

@DerHerzog7's EX5 on the iOS app came out of setup with no x-vin and no word about it. Rapid climate just failed (#84). All three of his suggestions are in:

  • Each derivation candidate's result is logged at debug, and when none matches, one warning names the field to fill in. Neither line carries the VIN.
  • A Repairs issue points at Vehicle token under Configure when the derivation comes back empty, and clears as soon as a token is in place.
  • Derivation is retried at every start while the entry has no token, so once a new key lands, a restart is enough.

What this doesn't do is derive the token for his app build. As @shanehughes-ui worked out, that needs the key and IV from the iOS app, and nobody has those yet. Until then, the token read off the phone and pasted into Vehicle token is the way.

🗓️ Scheduled trip, as a service

geely_connect.set_scheduled_trip (admin-only) arms or disarms the app's Scheduled trip, with an optional new departure (#4). It reads the car's current schedule first and sends it back with only what you changed, and it refuses rather than invent a departure when the car has none. On a 1.0-catalogue car it refuses before sending anything, because that car's request has never been seen, and on the new platform it isn't available yet. The body is @aheath70's capture from the app.

It is not yet confirmed to move a real car. If you have a schedule set in the app, one stop and one start, with a look at the app's Scheduled trip screen in between, would settle it. Please report on #4.

🔧 Manifest

cryptography, certifi and Pillow are no longer listed as requirements. Home Assistant ships all three itself, and its validation now rejects a custom integration that lists them. Nothing changes at runtime.


Full gate on release: 1008 tests, 0 failed, 0 skipped, coverage 100%.

v1.52.0 - the fast charge, and the way back

Choose a tag to compare

@YossiKon YossiKon released this 14 Sep 05:04

A release of field reports: every line of it came from an owner running into something and writing it down.

⚡ A DC fast charge, on its own

Two new diagnostic entities - DC Charge Current and DC Charge Voltage - that show a fast charge by itself and stay blank on AC and when idle.

The voltage is deliberately the charger's own output (dcChargePileUAct), not the pack's. The pack figure is what Charge Voltage already reports, and it is the one a car can send mis-scaled - the 1586 V of #17 - while the pile field is what the fast charger says it is delivering, and nothing surfaced it until now.

Both are gated on the same DC verdict Charging Power uses, because these fields read stale when idle: a parked, or even a driving, car still reports the voltage from its last fast charge. A gap beats a number that was true an hour ago.

Written and running live by @shanehughes-ui on an AU EX2 (#79), with the caveat he stated himself rather than let anyone discover: the fields are confirmed present on a real new-platform car, but the readings during a session are inferred from the #10 fast-charge log, not captured. They fail to a gap if a real session disagrees - so if you fast-charge, a diagnostics download taken while it is happening is the one thing that turns this from inferred to measured.

Entity counts move from 84/97 to 86/99 (battery-only / with a tank).

🔧 Coming back from the new platform no longer bricks the entry

@TDRobb tried the new Geely EM backend, went back to the original one, and landed on KeyError: 'device_id' - a config entry that would not load, with no button on it. The only way out he could find was restoring his whole Home Assistant from a backup. It was not a setting he had missed.

Switching to the new backend drops the legacy credentials, correctly: on a genuinely migrated account they are dead. Switching back restored only the session token, so the entry returned with no device id, no client certificate and no region - and setup then indexed them.

Both halves are fixed. The flow now re-provisions that half on the way back, through the same helper a first-time setup uses, and setup no longer indexes what it cannot assume: a legacy entry missing any credential raises a proper re-authentication prompt naming what is gone. An entry stuck in that state is now repaired by re-authenticating (#81).

🔧 The device lookup Home Assistant is about to remove

device_registry.async_get_device stops working in Home Assistant 2027.8, and cores already warn about it (#78, @TDRobb again). The lookup now asks the registry for the entry-scoped replacement and uses it when the core has one, falling back otherwise - because that replacement does not exist on 2026.7, and this integration supports cores back to 2024.12. Importing it would have turned a 2027 deprecation into an immediate failure to load on every older install.

🚙 A blueprint for a one-off departure

The existing pre-condition blueprint schedules a weekly pattern. @DerHerzog7 wanted the other case - a single trip, set the night before - so there is now a blueprint for exactly that: point it at a date-and-time helper, choose how many minutes ahead, and the climate comes on once.


Full gate on release: 970 tests, 0 failed, 0 skipped, coverage 100%.

v1.51.0 - the doors

Choose a tag to compare

@YossiKon YossiKon released this 06 Sep 21:25

The last command the new platform was missing, and the one that took the longest to earn.

🔒 Door lock and unlock on the new Geely EM platform

A car that has been migrated to the new backend can now be locked and unlocked from Home Assistant, completing the command set that landed in 1.48.0.

Why this one waited six weeks while the rest shipped. The mapping is RDL+start to lock and RDU+stop to unlock - and RDU is not "unlock". It is a general open service whose command differs per target, so the obvious reading of the names is wrong, and a mapping reversed here would send a car to open when you told it to lock. That is not a bug you discover from a log; it is one you discover in a car park.

So it was held to a bar the rest of the commands did not have to clear: a second owner, on a different car, running the full cycle. @shanehughes-ui captured the mapping on his EX2 and established the directions against the car's own centralLockingStatus rather than the service names - the right method, and one he had already used to correct himself once. @lanpup then pulled the branch and locked and unlocked his own car from Home Assistant, standing at it.

Two owners, two vehicles, the cycle behaving as the mapping claims. A service the catalogue does not cover still answers with a clear "not mapped" error rather than sending a guessed body to a car.


That closes the new-platform command block. For a migrated owner, everything now works from an email and a password: the vehicle read, the x-vin derived and verified automatically, find and lights, windows, climate, the position wake - and the doors.

Full gate on release: 961 tests, 0 failed, 0 skipped, coverage 100%.

v1.50.0 - altitude you can plot

Choose a tag to compare

@YossiKon YossiKon released this 06 Sep 18:40

One entity, and the reason it took a release of its own.

📈 Altitude is a sensor now, so you can graph it

The car has always reported its altitude, and this integration has always carried it - but only as an attribute on the device tracker. An attribute has no unit and no state class, which means Home Assistant records no statistics for it: you could read the number on a tile and never plot it, which is what @TDRobb ran into (#77).

It is now a curated sensor in metres with a measurement state class, so history, the trend card and long-term statistics all work with no further setup. The device-tracker attribute stays exactly where it is - nothing that reads it today changes.

Metres is not an assumption: two cars on two continents settled it - 1768 on a Colombian EX2 and 41 on a South African E2, each plausible for where that car is and neither plausible in any other unit.

Two details that keep it honest: it is a measurement, not a total, because total_increasing would read every descent as a counter rollover; and a car that reports no altitude gets an empty sensor rather than a confident zero, since sea level is a real place.

Entity counts move from 83/96 to 84/97 (battery-only / with a tank).


Still not in a release: new-platform door lock / unlock (#55). A second owner has now confirmed the mapping on his own car - the bar it has been held to since August - and it will ship on its own once the maintainer signs it off.

Full gate on release: 957 tests, 0 failed, 0 skipped, coverage 100%.

v1.49.0 - the readings owners could not trust

Choose a tag to compare

@YossiKon YossiKon released this 06 Sep 18:07

Two bugs owners were living with, fixed from their own diagnostics - plus the windows control on the cards, an Italian card, and a charging reminder.

🌡️ Exterior temperature: 131 °C, and why no offset could fix it

Two owners - an EX2 in Colombia and a Geely E2 in South Africa - reported exterior temperatures of 110-131 °C while the real air was 25-28. It looked like a bigger version of the +10 offset this project already knew about, and it was not.

Their payloads carry exteriorTempValidity: "false" right beside the reading. The car is not sending a temperature that is a hundred degrees out; it is saying the slot holds whatever was last left in it. That is a value no offset could ever have corrected, because it was never a measurement.

The sensor now publishes unknown when the car marks the reading invalid - the same contract speedValidity already had here. Two things keep it safe: the guard fires only on an explicit false, so any car that never sends the flag is untouched; and it runs before the per-entry offset, since an offset applied to a disowned value only produces a wrong reading that looks deliberate.

Reported by @sibero80 (#24) and @maknij (#72), both with the diagnostics that settled it.

🔒 The lock entity that sat at Unknown

On a South African E2, lock.<car>_doors read Unknown through every lock and unlock while the four door-lock sensors beside it correctly read Locked. The car sends all four doorLockStatus* fields and no centralLockingStatus - which was the only field this entity read. The owner ended up rebuilding the aggregate himself in a template.

It now falls back to those four fields when the central one is absent. Sound because they were captured moving in lockstep with centralLockingStatus on a car that sends both; the fallback applies only where the central field is missing, and a car that sends neither still reads Unknown rather than a confident "unlocked". Reported by @maknij (#72).

🪟 Windows on the cards, and how far open

The windows command shipped in 1.48.0, but no card could drive it. The climate panel on the full and top cards now carries a Windows row - Open / Close, lit while they are open - and the compact card gains a windows chip.

The aggregate cover also reports a position: the car sends a per-corner winPos beside each winStatus, so a vent crack reads as a percentage rather than just "open". Capture-verified on a new-platform EX2; legacy cars send no winPos and simply show no percentage. By @shanehughes-ui (#73).

🇮🇹 The cards speak Italian

A complete Italian dictionary for the dashboard cards, by @manuele84 (#75) - joining English and Thai.

One string needed changing before it shipped, and it is worth explaining: {plural} is substituted with the English letter "s", so "{count} apertur{plural} aperte" would have rendered "1 apertur aperte" / "2 aperturs aperte". Reworded to phrase around the count. A new test now reads every shipped dictionary and fails on a missing or unknown key, an empty value, an invented {token}, or any use of {plural} outside English - so the next language cannot trip over the same undocumented token. It earned its place immediately, catching a missing Italian key in #73.

⏱️ Compact card: an opt-in charging countdown

With charging_countdown: true, a charging session on the compact card reads Charging · 1.7 kW as a status line with a Ready 10:22 · 2h 15m left chip that ticks down each minute between polls. Off by default - an unset card is unchanged. The minute timer runs only while a countdown is on screen and is cleared when the card goes away. By @shanehughes-ui (#76).

🔌 "Plugged in but not charging"

The charging blueprint gains a fourth branch: if the car sits plugged in past a grace period with no session started - a wall switch left off at the socket - it tells you, instead of staying silent until you find out hours later that the car never charged. It stays quiet near full, and clears itself when charging starts. All new inputs have defaults, so an existing automation is unchanged; set the reminder level to 0 to switch it off. By @shanehughes-ui (#74).


Not in this release: new-platform door lock / unlock (#55). A second owner has now confirmed the mapping on his own car, which was the bar - it goes in on its own, not bundled into a release minutes after its first independent confirmation.

Full gate on release: 955 tests, 0 failed, 0 skipped, coverage 100%.

v1.48.0 - the new platform learns its commands

Choose a tag to compare

@YossiKon YossiKon released this 02 Sep 18:26

Almost everything here came from contributors, and everything was verified end to end - live captures, browser tests and the full gate - before landing.

The new platform learns its commands (#60, includes #59)

A migrated car - addressed by its x-vin vehicle token - now sends its remote commands through the new gateway's own control route, instead of the legacy telematics endpoint that answers 8060 for it:

  • Find / lights - confirmed working on two Australian cars
  • Windows, sunshade and vent
  • Rapid heat / cool - the platform's dedicated setSmartTemp route
  • G-Clean, seat and steering-wheel heat, defrost
  • GPS position refresh (PAI) - the fix for the hours-stale map on a migrated car

An unmapped service fails loudly ("not mapped") rather than sending a guessed body to a vehicle - and door lock / unlock is deliberately in that set, held on #55 until a second owner confirms the mapping, because its failure mode is a car that opens when told to lock. control() now debug-logs which route each command took, so the next mystery is a log line instead of an inference.

Command mapping and captures by @shanehughes-ui, live-tested on his EX2; Find confirmed independently by @lanpup.

The GPS wake stops running on a timer

The position wake reaches the car and spends its 12 V battery, so it now fires only when the fix could actually be wrong: while driving, once more on the poll after parking, when the odometer moved without a drive being observed, and on Refresh Data. A car that has not moved is never woken to be asked where it is, however long it sits. A car whose odometer cannot be read keeps the old cadence - nothing loses coverage.

The cards speak your language (#70, closes #68)

Every label on the five dashboard cards follows Home Assistant's UI language - English and Thai ship today, by @tomzt. hass.localize() can never reach a Lovelace card (the frontend only loads its fixed set of translation categories), so the card carries its own string table with a three-tier fallback - language, then English, then the coded default - and switching HA's language re-renders immediately. Adding a language is one STR block in geely-card.js; PRs welcome. The config dialogs gained Thai too (#67, docs in #71).

Cards: an owner's car, an owner's photo (#62, #64, #61 - all @shanehughes-ui)

  • Your own car photo on the cards, with tap-to-expand from the compact card to the full one
  • Compact-card display options - hide_name, battery_size, battery_bold, charge_time_format, show_parked
  • Seat and wheel heat levels render as a proportional fill instead of a fixed glow

Driving state no longer flickers to Parked on the new platform (#65)

The new gateway spells engine-off with a hyphen where the old one used an underscore; the poll-flag reader now normalises the separator, so a driving car stays "Driving" (@shanehughes-ui).

A live charging countdown on your lock screen (#66)

A ready-made Blueprint sends a notification that updates in place while the car charges - percentage, power and time to full - and clears itself when charging stops (@shanehughes-ui).

Also

  • The README now documents the migrated-account setup (the x-vin vehicle token, shipped in v1.46 and undocumented until now) and the real, current state of the new platform - what is live-verified and what is deliberately held.

Full gate on release: 924 tests, 0 failed, 0 skipped, coverage 100%.

v1.47.0 - new-platform read entities and capability catalogue

Choose a tag to compare

@YossiKon YossiKon released this 28 Aug 16:41

Read-side improvements for the new Geely EM platform, split cleanly from the command work by @shanehughes-ui (#58). No control code here - commands remain on #55, held for a second owner to confirm the lock/unlock mapping.

The status wrapper now moves rather than copies

The new gateway sends its status blocks at the top level; the wrapper re-nests them under vehicleStatus so every existing entity works unchanged. It used to copy them, which left every field reachable at two paths - and the full-exposure sweep, which skips only curated vehicleStatus.* paths, turned each duplicate into an extra raw diagnostic entity: about two hundred on a real car. It now moves them, so there are no twins. Only the new-gateway read path is wrapped; no old-platform car is affected.

New read entities

Checked against a real old-platform payload before shipping ungated, so they populate on existing cars too, not just new-platform ones:

  • four per-door locks (Door Lock Driver / Passenger / Rear-Left / Rear-Right) - the aggregate lock says whether the car is locked, these say which door is not;
  • Trip Meter 2, the second trip counter beside the first;
  • the vehicle-to-load discharge pair (current and voltage).

Two more - Charging (reported) and Plugged In (reported) - are new-platform-only fields, so they are gated behind the x-vin token and never appear on a car that cannot populate them.

Capability catalogue for the new platform

The new gateway's ms-vehicle-capability catalogue is now read and parsed, on the same signer and x-vin addressing as the status read - read-only, no new host or secret. Groundwork for capability-driven entities on that platform.

Thank you again to @shanehughes-ui, whose migrated account is where all of this was traced and verified.