PLAN.md
upApp: upXlink as an Android app
Kotlin Android app that talks to the media unit of a VW e-up! (and Citigo e iV / Mii electric). It reimplements two Python projects:
- MIBBridge: tunnel protocol over Bluetooth RFCOMM channel 5.
- upXlink: registration, TLS-PSK session, REST (VIWI) access, entity parsing.
How the original works
- Phone opens RFCOMM channel 5 to the car.
- MIBBridge protocol multiplexes virtual TCP connections over that socket.
Segment header:
port u16le | type u8 | .... Types: TRANSMIT 0 (len u16le+ data), OPEN 1 (dst u16le), CLOSE 2, HEARTBEAT 3 (echo it). GET http://car:80/car/info/vin(plain HTTP) returns the VIN.- No stored credentials for that VIN:
POST http://car:80/auth/registrationreturns 303 withcontent-location.GET https://car:443<location>with TLS 1.2,ECDHE-RSA-AES128-GCM-SHA256, no cert check, legacy renegotiation allowed. The user confirms a PIN on the car display. The body isusername,password. - All further requests use TLS 1.2 with
PSK-AES128-CBC-SHA256(identity = username, key = password). - REST endpoints:
/car/batteries,/car/info,/car/ranges,/chargingmanager/{providers,profiles,timers}. The first profile is the default profile. Departure times are UTC.
Key technical decisions
- TLS: BouncyCastle low-level API (
bctls). Android's Conscrypt (BoringSSL) has noTLS_PSK_WITH_AES_128_CBC_SHA256. BC'sPSKTlsClientsupports it. BC also lets us skip cert checks and allow legacy renegotiation for registration. - No localhost TCP bridge. MIBBridge listens on local ports so that
requestscan connect. On Android we run TLS directly on the in-process tunnel streams. This removes ports, threads and the proxy layer. - Minimal HTTP/1.1 client over the TLS stream (request line, headers, Content-Length or chunked body). OkHttp cannot use a BC TLS-PSK stream.
- JSON:
org.json(part of Android). No serialization library. - Credentials: app-private SharedPreferences keyed by VIN.
allowBackup=false. - Bluetooth: pick from bonded devices, no scanning. Permission
BLUETOOTH_CONNECT(API 31+). Connect by the SDP service UUID from maps+more. See docs/maps-and-more.md. - UI: Jetpack Compose, Material 3, single activity, coroutines on
Dispatchers.IO. - License: AGPL-3.0-or-later (EUPL-compatible). Attribution to upXlink and MIBBridge in the README.
Files (target)
app/src/main/java/.../
Tunnel.kt MIBBridge segment codec, reader loop, heartbeat, virtual connection streams
Tls.kt BC TLS clients: registration (ECDHE-RSA) and session (PSK)
Http.kt minimal HTTP/1.1 request/response
Car.kt connect flow: VIN, credentials, registration, get/post
Model.kt Battery, Info, Range, ChargingManager parsing
MainActivity.kt Compose UI: device picker, dashboard, charging manager, raw GET/POST console
app/src/test/... codec test, parser tests (ported from upXlink fixtures)
Phases
- Setup. Android SDK, Gradle project, JDK 21.
- Transport. Tunnel, TLS, HTTP, registration, raw GET/POST console. First car session: register and read
/. - Read parity. Battery, range, info, charging manager. Unit tests with the upXlink fixtures.
- Roadmap items (see below). Each needs car sessions.
- Docs. README with protocol notes and the endpoint list we discover.
Roadmap items from upXlink
| Item | Status | Needs |
|---|---|---|
| Charging manager write | Done | Tested in the car: timer edits, off-peak days, location create and delete. Location and options edits untested. |
| WebSocket events | Done | Tested in the car. |
| Cert check at registration | Done | Tested in the car. |
| PIN calculation | Done | Tested in the car. |
| Documentation | Done | README and docs/maps-and-more.md. |
| MediaControl | Open | Explore / and /media/* on the car. Scope depends on what the car exposes. |
| Infotainment keys | Open | Events arrive and are logged. Map keys to screens, like maps+more. |
| Missing location fields | Open | Temperature, min. level, more operations in the location editor. |
| Car clock sync | Open | maps+more sets the car date and time from the phone. |
| Release build | Open | R8, signing, Play listing. Debug logging of raw responses still on. |
Debugging in the car
- Laptop to phone over USB or wireless adb: install,
logcat, run the raw console. - API exploration needs no new code: run upXlink on the laptop over the laptop's own Bluetooth.
- Optional: Bluetooth HCI snoop log of maps+more. Payloads are TLS encrypted, so value is limited.