# 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 1. Phone opens RFCOMM channel 5 to the car. 2. 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). 3. `GET http://car:80/car/info/vin` (plain HTTP) returns the VIN. 4. No stored credentials for that VIN: `POST http://car:80/auth/registration` returns 303 with `content-location`. `GET https://car:443` 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 is `username,password`. 5. All further requests use TLS 1.2 with `PSK-AES128-CBC-SHA256` (identity = username, key = password). 6. 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 no `TLS_PSK_WITH_AES_128_CBC_SHA256`. BC's `PSKTlsClient` supports 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 `requests` can 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 1. **Setup.** Android SDK, Gradle project, JDK 21. 2. **Transport.** Tunnel, TLS, HTTP, registration, raw GET/POST console. First car session: register and read `/`. 3. **Read parity.** Battery, range, info, charging manager. Unit tests with the upXlink fixtures. 4. **Roadmap items** (see below). Each needs car sessions. 5. **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.