Skip to content

Reused one of your capabilities and added more translations, remove ps2#6

Open
kaohlive wants to merge 78 commits into
Coderaxx:masterfrom
kaohlive:master
Open

Reused one of your capabilities and added more translations, remove ps2#6
kaohlive wants to merge 78 commits into
Coderaxx:masterfrom
kaohlive:master

Conversation

@kaohlive

Copy link
Copy Markdown
Contributor

No description provided.

@kaohlive

Copy link
Copy Markdown
Contributor Author

Here is a new pull request, it cleans up the vehicle driver and adds translations for NL in your driver.
I also switched to the polestarbattery measurement instead of the measure_battery. For a car the number view is more usefull than the bar icon and the battery warning also is not usefull IMO.

@kaohlive

Copy link
Copy Markdown
Contributor Author

@Coderaxx can you merge this request please?
This version should be ready for a release IMO and would like to see it released.

@kaohlive

Copy link
Copy Markdown
Contributor Author

@Coderaxx hey, I added support for the new feature of showing the charing KW and amps to the vehicle driver. Very nice that it is now available.
Can you please merge this pull request?

kaohlive added 19 commits May 6, 2024 23:09
Changelog: Added support for charge speed details
Changelog: Changed polestar vehicle to new device class car
Changelog: Fix for trigger events
Changelog: hotfix on the csv driver
Changelog: Improved insights on power measurements
Changelog: update to fix api changes
Changelog: Update npm modules
Changelog: Widget, service warning and login bug fix
Changelog: preview images
Changelog: fix widget update on device state change
kaohlive and others added 30 commits June 12, 2025 22:52
Changelog: Fixed CSV receiver driver
Changelog: Added upgrade path for existing cars for homey energy
Changelog: More rebost energy upgrade detection
Changelog: Changed api, no linger supports images
Changelog: Changed api, no linger supports images
Changelog: Added support to switch to miles
Changelog: Rounding and stability improvements
Replace the legacy @andysmithfal/polestar.js GraphQL path with a
purpose-built C3 client (clone_modules/polestar-c3/) that talks raw
HTTP/2 gRPC against the same backend the Polestar mobile app uses.
This unlocks fields the public GraphQL stopped returning (power,
current, voltage, charge type) and brings new telemetry (tyre
pressures, lifetime driving consumption, per-session charge kWh).

Restored capabilities: measure_current, measure_power, meter_power
(the last one now accumulates cleanly during CHARGING instead of
being overwritten by unrelated driving-consumption values).

New capabilities: measure_voltage, measure_polestarChargingType,
measure_polestarDrivingKwh, measure_polestarSessionKwh,
alarm_polestarTyrePressure, measure_polestarTyrePressureFL/FR/RL/RR.

The new client is zero-native-deps (Node's built-in http2 + a
minimal protobuf varint codec) so it drops straight onto Homey Pro.
A c3_backend_disabled setting falls back to the legacy client as a
rollback lever for any account where C3 misbehaves.

Bumps to 2.8.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire the C3 chronos services (ChargeNow, TargetSoc, AmpLimit) through the
JS client so users can actually control their car from Homey, not just
read status. Adds flow action + condition cards and in-tile sliders for
charge limit and amp limit plus momentary Start/Stop charging buttons.

Device setting "Allow remote commands" is a master-switch kill-flag —
writes fail instantly when turned off. Replaces an earlier PIN prototype
that produced ugly titleFormatted strings.

Device setting "Charge limit slot" (Daily/LongTrip/Custom/Unspecified)
is exposed because Polestar 4 silently rejects writes to the Daily slot
but commits to Custom — and we don't yet know which slot other models
prefer. Default stays on Daily to match the Python reference; Polestar 4
users switch once. Writes that don't land surface a log warning pointing
at this setting.

gRPC reliability: HTTP/2 keep-alive ping every 30 s, goaway-event handler
that nulls the session eagerly, and one automatic retry on transient
errors (INTERNAL/UNAVAILABLE/GOAWAY/ECONNRESET/ETIMEDOUT) with a fresh
session. Resolves the cold-session GOAWAY hit we saw on the first write
after idle.

UNIMPLEMENTED responses are now captured in a persistent device-store
flag so unsupported features (e.g. Polestar 4 returns "Functionality not
supported: AMP_LIMIT") hide the slider tile and skip further calls on
subsequent runs instead of spamming the log forever.

Charge limit polling moved to the fast 60 s cycle (down from 15 min) so
changes made in the Polestar app or in-car menu show up within a minute.
Amp limit stays on the slow 15 min cycle — it rarely changes and is
skipped entirely on vehicles that don't support it.

Set-response parsing no longer trusts the echoed level: the P4 chronos
envelope returns a stale value, so we rely on a delayed Get 3 s after
the write to reflect the committed state. The slider stays on the
user-chosen value until that re-read either confirms or corrects it,
avoiding the disorienting snap-back-then-forward UX.

The custom measure_polestarTyrePressure{FL,FR,RL,RR} capabilities are
also migrated to measure_pressure.{front_left,front_right,rear_left,
rear_right} with a kPa unit override — the standard capability gets
better UI + Insights integration. Legacy JSON files remain with a
_deprecated marker so existing devices can migrate via removeCapability;
they will be deleted in a future release.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire two more C3 services so the car's external closures and parking
climatization show up as Homey tiles:

  ExteriorService/GetLatestExterior  — locks, per-door/window open state,
  hood, tailgate, sunroof, charging-port cover
  ParkingClimatizationService/GetLatestParkingClimatization — running
  state, target temperature, interior temperature, minutes remaining

Both are unary calls on the 60 s fast cycle so a user walking up to the
car sees door-opened alarms within the minute.

Homey capabilities chosen so they can be switched to setable later
without a rename, once lock/unlock + climate start/stop writes land:

  locked                     — central lock state (setable:false for now)
  onoff.climate              — climatization running/not (setable:false)
  target_temperature         — last requested temp (setable:false)
  measure_temperature        — interior temperature (inherently read-only)
  measure_polestarClimateRemaining — minutes left on the 30-min parking
                               climatization session; blank when idle
  alarm_contact.door_{fl,fr,rl,rr} — per-door open alarms
  alarm_contact.window_any   — aggregate window-open alarm
  alarm_contact.{tailgate,hood,sunroof,tank_lid} — body + charge port
                               open alarms

The capabilitiesOptions setable:false overrides keep the tiles visible
as read-only indicators. When writes arrive they just drop the override
and register listeners.

DigitalTwin flat-field format was reverse-engineered against a live
Polestar 4 session: exterior fields 2-16 hold ints (LockStatus enum on
2/16, OpenStatus 1/2/3 on all others), climate fields 2,3,7,8 are the
ones we trust (running_status, time_remaining in minutes, current and
requested temperature as float32). ventilation_only and request_type
are still speculative per-model so they stay in debug logs only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Complete the invocation surface so every write Polestar's mobile app
offers is available from Homey flows and device tiles, plus a couple
of reads that round out the picture.

Writes (via /invocation.InvocationService):
  lock / unlock                  — wired to the setable `locked` tile
  unlock_trunk                   — tile button + flow action
  honk_flash                     — tile button (flash-only default) +
                                   flow action with HONK/FLASH/BOTH
  climate_start / climate_stop   — onoff.climate toggle reads seat and
                                   steering-wheel heating defaults from
                                   new device settings; a separate flow
                                   action exposes all 6 params per-call
                                   for one-off custom sessions
  windows_open / windows_close   — flow actions (OPEN_ALL / CLOSE_ALL —
                                   the API doesn't support per-window)

Reads:
  Location (/dtlinternet.DtlInternetService/GetLastKnownLocation) —
    parser handles three documented response layouts, populates a
    measure_polestarLocation string tile on the 15-min slow cycle.
    A get_location flow action refreshes on-demand and exposes
    latitude, longitude, and a formatted "lat, lng" string as tokens
    for downstream cards (push notifications with a map link).
  OTA (/ota_mobcache.OtaDiscoveryService/GetSoftwareInfo) —
    alarm_polestarOtaAvailable fires on DOWNLOAD_READY /
    DOWNLOAD_COMPLETED / INSTALLATION_DEFERRED / INSTALLATION_SCHEDULED.
    State text falls back to a friendly "No pending update" when the
    car returns an empty CarSoftwareInfo (no update queued).
    Write side (schedule/install/cancel) deliberately omitted — the
    risk of a misconfigured flow triggering an install mid-drive
    outweighs the convenience over the Polestar app.

Flow cards:
  11 action cards (charge ±, limits, lock ±, trunk, honk, climate ±,
  windows ±, get_location)
  3 conditions (is_locked, target_soc_is, amp_limit_is)
  1 condition trigger (is_locked) + standard triggers from button.*,
  locked, onoff.climate capabilities.

Housekeeping:
  The four legacy measure_polestarTyrePressure{FL,FR,RL,RR} JSONs are
  removed — they never shipped in a release and the migration loop
  that would auto-remove them from existing devices is gone too, since
  no one has those capabilities in their device state. All current and
  future users take the standard measure_pressure.* sub-IDs directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps to 3.0.0 and wraps up the C3-migration work.

- Mark the legacy polestar-2-csv driver as deprecated via Homey's
  official driver flag so new pairings are rejected but existing
  devices keep working. The Car Stats Viewer webhook still supplies
  live telemetry the C3 backend doesn't expose (speed, gear,
  ignition, battery temperature, trip summaries) so it stays around
  for P2 owners who rely on it.

- Rewrite README.md with real feature list and deprecation note,
  rewrite README.txt (app-store listing) with concrete read/write
  capabilities and a privacy section, and refresh the
  .homeycompose/app.json description + tags to reflect what the
  app actually does now instead of generic marketing copy.

- Drop the `measure_power: { approximated: true }` override. The
  new C3 client returns real power_watts from the car, not a
  calculated estimate, so Homey Energy can treat it as a real
  sensor reading.

- Add a `windows_supported` device setting and wire it into the
  same OPTIONAL_FEATURES machinery that already auto-hides
  amp_limit on Polestar 4. Unchecking hides the two window
  buttons; the backend auto-disables the feature when it returns
  UNIMPLEMENTED.

- Make `target_temperature` fall back to the configured climate
  default when the C3 climatization response has no
  requested_temp (happens whenever climate isn't running). Tile
  no longer stays empty on a fresh device.

- After every state-changing write (lock, climate, windows,
  charging, trunk) schedule two follow-up reads at +3 s and +10 s
  so the UI reflects the actual state faster than the 60 s regular
  poll cycle. Window opens/closes use a wider +15 s second refresh
  because physical movement takes longer to complete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Point every custom capability used by the active vehicle driver at an
SVG in drivers/vehicle/assets/ so the driver stops depending on files
that live in the deprecated polestar-2-csv driver's folder. Copies
battery-75, battery-100, powerdc, hvbattery, location and update from
the CSV driver into the vehicle driver's own asset folder.

Add tire-pressure.svg and wire it to alarm_polestarTyrePressure —
Homey threw a render error on the iconless alarm tile.

Fill in the two remaining missing icons (alarm_polestarOtaAvailable,
measure_polestarOtaVersion) with update.svg so all three OTA
capabilities share the same glyph.

CSV-only capabilities (speed, gear, ignition, temperature, etc.)
keep pointing at their own driver's assets — they live together and
will move as a set when that driver is eventually removed.

Adds a 3.0.0 changelog entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Changelog: Polish on icons etc
Polls kept firing after a device was removed or while the app was
restarting, so each in-flight updateVehicleState() eventually hit
setCapabilityValue on a device Homey had already forgotten about —
surfacing as 'Not Found: Device with ID …' in the app log.

Adds a _cleanup() that clearIntervals both poll timers and closes the
gRPC session, invoked from onDeleted() and onUninit(). Every update
method (vehicle, health, exterior, climate, location, ota) and the
post-write _scheduleStateRefresh closures now early-return when
_destroyed is set, so in-flight promises can't race past the cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- CHARGING_STATUS_DONE now surfaces as 'plugged_in' instead of
  'plugged_in_paused'. A completed session is not a pause — the
  Polestar app shows "Finished" for this state, and users were
  getting "Paused" on their Homey tile.

- Honk/flash flow card retitled to "Find my car — [action]". The
  previous titleFormatted was just the action value, making the
  card hard to identify in a flow list.

- Added a 'Start climate (defaults)' flow action that takes no
  arguments and reads temperature + seat/steering heating from
  device settings. Mirrors the one-tap climate behaviour of the
  Polestar mobile app; complements the existing argument-driven
  climate_start action for custom sessions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Car Stats Viewer Android app sometimes pushes driving points with
no altitude or state-of-charge field (GPS dropout, sensor delay).
trip-ended trigger then crashed on undefined.toFixed(0).

Replaces the bare .toFixed() calls with a fmt() helper that checks
Number.isFinite first and falls back to the existing "Unavailable"
localization. energy_delta accumulator also now defaults a missing
field to 0 so a single bad point can't NaN the whole sum.

Touches only the deprecated CSV driver; the new vehicle driver is
unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two issues spotted in a tester's pair-flow log.

- The settings-changed listener was logging user_email and
  user_password values verbatim. Even though the password is
  encrypted-at-rest, dropping the ciphertext in a debug log is the
  kind of thing that ends up in a screenshot. Now we log only
  '[N chars]' or '[empty]' for user_email, user_password, and
  polestar_token.

- testlogin returned a plain boolean, so the pair UI couldn't tell
  the difference between 'login failed' and 'login OK but the
  account has no vehicles'. Both paths showed the same red
  'Login validation failed' alert, which confused at least one
  tester whose login was actually fine. testlogin now returns
  { ok, reason } so the HTML can show a specific 'no vehicles'
  message that points at account selection or a transient backend
  hiccup as likely causes. Old boolean return is still accepted
  by the pair view as a fallback.

While in the area, fixes a small bug where a 'Credential test ok'
log line referenced `vehicles` before its var was declared.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mark_Beech (self-hosted Homey) hit an unhandledRejection during
pairing because his network interfaces are not named wlan0/eth0/eth1
— the salt derivation in lib/homeycrypt.js fell off the if-else chain
with mac=null and crashed on null.join('').

Adds a fallback that iterates os.networkInterfaces() and picks the
first non-internal interface with a non-zero MAC, sorted by name so
the same interface keeps being chosen across reboots. Preserves the
preferred wlan0/eth0/eth1 order so existing users' encrypted
passwords still decrypt with the same MAC they were salted with.

If no usable MAC can be found at all (extremely rare, would only
happen in a stripped-down container), throws an explicit error
instead of the cryptic null.join crash.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Translations: added de, fr, it, sv, es, da, ru, pl, ko, ja to every
capability title/unit, driver name, driver capabilitiesOptions, flow
cards (titles, hints, titleFormatted, dropdown labels, tokens), and
device settings (labels, hints, dropdown values). Source en/no/nl
strings preserved verbatim. AI-generated — non-elegant phrasing can
be reported and fixed in follow-ups.

Widget: the charging block now mirrors the orange-label / white-value
pattern of charge and range. Power (kW) is the primary number; current
and time-remaining form a subtitle. Numbers gracefully fall back to
"— kW" / omitted parts when capability values are missing, instead of
showing "0 A | 0 kW · 0h 0m".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The legacy Car Stats Viewer driver stored a webhook_slug only when the
deprecated trip-image API was used. Newer pairings leave it null, but
the trip-ended handler still ran `base64url.encode(this.slug)` as the
first step. That throws ERR_INVALID_ARG_TYPE on null and aborts the
trigger before any flow ever fires.

The encoded slug fed only image URLs that are now fully commented out,
so the line is removed entirely along with its commented-out block.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.2.2 left the lastTrip/tripInfo/tripScore image tokens in the flow
definition (removing them would break user flows referencing those
tokens) but the trigger payload no longer supplied them, so every
trip-ended event threw "Invalid value for token lastTrip. Expected
object but got undefined".

Create three Homey images on device init, all pointing at the driver
brand asset. The token payload is schema-valid again; existing flows
keep firing. Per-trip renders are gone with the deprecated backend, so
notifications now show the Polestar driver image instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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