Skip to content

Kia EU: fix commands on legacy (non-CCS2) vehicles#34

Merged
schmidtwmark merged 1 commit into
schmidtwmark:mainfrom
hillmar:kia-eu-legacy-v1-fix
May 28, 2026
Merged

Kia EU: fix commands on legacy (non-CCS2) vehicles#34
schmidtwmark merged 1 commit into
schmidtwmark:mainfrom
hillmar:kia-eu-legacy-v1-fix

Conversation

@hillmar

@hillmar hillmar commented May 27, 2026

Copy link
Copy Markdown
Contributor

Mirrors @Nachtlatscher's #32 for Hyundai Europe — the same three bugs exist in the Kia Europe client and were flagged on the #29 thread.

Fixes

  1. Leading slash on door commands (KiaEuropeAPIClient+Commands.swift). lock/unlock returned "/control/door" while every other legacy case returned "control/...", so the URL builder produced a double slash (…/spa/vehicles/<id>//control/door).

  2. Control-token used on legacy endpoints (KiaEuropeAPIClient.swift). sendCommand unconditionally fetched a PIN-derived control token and used commandHeaders (Authorization: Bearer <controlToken>). Legacy v1 endpoints reject this with 400 "Authorization field missing" — they expect the regular access token. Gate the control-token flow on ccs2; legacy uses authorizedHeaders(authToken:ccs2:) directly.

  3. commandPathAndBody always took the CCS2 branch. The call site passed no ccs2: argument, so the default ccs2: true always selected the CCS2 path/body shape — even for legacy vehicles whose URL was being built as v1. Pass ccs2: ccs2 explicitly.

Validation

Live-tested against my CCS2 Kia EV9 by hard-coding ccs2 = false locally to force the legacy branch:

  • Before fix: `POST /api/v1/spa/vehicles///control/door` → `400 "Authorization field missing"` (both bugs visible — double slash + control-token rejected).
  • After fix: `POST /api/v1/spa/vehicles//control/door` with `{"action": "close/open", "deviceId": "..."}` → `200 resCode "0000"` for both lock and unlock. Doors physically locked/unlocked, which incidentally confirms that the Bluelink backend routes both legacy v1 and CCS2 endpoints to the same vehicle-command handler.

Normal CCS2 path on my EV9 unchanged (still works, 286/286 tests pass).

A true CCS1 vehicle owner would be the ideal validator, but the wire-level fix is confirmed by the symmetry with #32 and the Python reference (`ApiImplType1`).

🤖 Drafted with assistance from Claude Code (Anthropic).

Mirrors the three legacy-path bugs Nachtlatscher fixed for Hyundai EU
in schmidtwmark#32 — flagged in the schmidtwmark#29 thread after merge.

- Drop leading slash on lock/unlock door paths so the URL builder
  doesn't produce a double slash.
- Stop using the PIN-derived control token on legacy v1 endpoints.
  Legacy endpoints reject control-token auth with
  "400 Authorization field missing" and expect the regular access
  token. Gate the control-token flow on ccs2 and use
  authorizedHeaders for the legacy branch.
- Pass ccs2: ccs2 to commandPathAndBody. The call site relied on
  the default ccs2: true, so legacy vehicles got the CCS2 payload
  shape against a v1 URL.

Live-validated against a CCS2 EV9 by hard-coding ccs2 = false
locally: lock + unlock both return 200 / resCode 0000 and the
doors physically lock and unlock — confirming the Bluelink
backend routes legacy v1 and CCS2 endpoints to the same handler.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@schmidtwmark schmidtwmark merged commit b83c22e into schmidtwmark:main May 28, 2026
1 check passed
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.

2 participants