Document the signed-ITS/VAM/BLE work and how it was verified
docs/06-signed-its-vam-ble.md: who does what between phone and ESP32-C5 (signing lives on the board), the link protocol, recovery paths (USB heartbeat watchdog, BLE supervision timeout and auto-reconnect, board-reset reconfiguration, app restart), the demo PKI, and what is still open. obu-firmware/test/verify_signed_pcap.py checks the IEEE 1609.2 signatures in a pcap with asn1tools and OpenSSL, independent of the firmware. On a capture of the CAM pinger (2026-09-23) all 12 signed CAMs verify under the demo ticket, whose chain verifies too. The CiT One receives the same CAMs but its MQTT interface exposes no security information, so it cannot confirm the signature itself. The V2X2MAP bridge on COM10 now verifies against the demo chain as well (change in the colleague's repository); signed CAMs and VAMs show as verified. TODO.md: bench checks confirmed so far ticked; open are BLE/ITS-G5 coexistence, time_regression over a longer stationary run, and board reset recovery over BLE.
This commit is contained in:
@@ -5,6 +5,107 @@ Engineering to-do list. The reviewer-facing open items live in
|
||||
|
||||
## Waiting on hardware
|
||||
|
||||
### Signed-TX firmware (vanetza-idf port), VAM and BLE: first on-air checks (added 2026-09-23)
|
||||
|
||||
obu-firmware is now a port of the colleague's `microbu-esp32c5` station (vanetza-idf, TS 103 097
|
||||
signing, station-link protocol, BLE GATT), built with **ESP-IDF 6.0.2**. See `obu-firmware/NOTES.md`.
|
||||
The previous firmware is backed up in `firmware-backups/` (restore command in its README.txt).
|
||||
The app speaks the new protocol over USB or BLE and still falls back to the old frames against the
|
||||
old firmware.
|
||||
|
||||
Done without hardware: IDF 6.0.2 build clean (39 % app partition free); host suite (`make` in
|
||||
`obu-firmware/test/host`) passes unchanged; app unit tests 103/103, including the VAM encoder
|
||||
against asn1tools, the station-link codec against the colleague's Python `messages.py`, and the VAM
|
||||
generation rules. Flashed to **COM3** 2026-09-23 (hash verified); boot log: IDF v6.0.2,
|
||||
`BLE advertising started as 'micrOBU-4AFA'`, station task ready. The radio stays off until the app
|
||||
configures the station. New app build installed on the Pixel 9 Pro (adb, `install -r`).
|
||||
|
||||
First phone session (user, 2026-09-23): BLE works and CAMs go out. Three faults, fixed and
|
||||
reflashed/reinstalled the same day:
|
||||
1. No RX until the CAM pinger ran, with ~177 RX-queue drops: the colleague's `Station::tick()`
|
||||
returned before draining the radio until the first PoTi had set the clock. Now drained always.
|
||||
2. "refused a request: time_regression": the loops re-send the latest fix every tick; a stale fix
|
||||
timestamp read as the clock going back > 1 s, and each time the board rebuilt its stack.
|
||||
`Esp32Link` now sends a PoTi only for a newer fix (or a >= 60 s real clock correction).
|
||||
3. BLE reconnect loop: GATT operations with a 5 s timeout ran during Android's pairing, cut it off
|
||||
and restarted it on every attempt. Encryption/pairing is now settled first (60 s), retries back
|
||||
off to 30 s, and every failure reason is logged and shown; the board logs encryption changes.
|
||||
|
||||
Second session (user, 2026-09-23): USB, RX and signing work; BLE still prompted every time and
|
||||
never connected; time_regression every ~8 s. Found and fixed, reflashed (full flash, NVS erased):
|
||||
4. The board never stored a bond: NVS (24 KB, the colleague's 4 MB-board layout) was full, mostly
|
||||
Wi-Fi settings the previous firmware left behind, and NimBLE's bond write failed. NVS is now
|
||||
80 KB (app moved to 0x20000) and was erased; boot logs `N bonded phone(s) in NVS`.
|
||||
5. The station loop waited `pdMS_TO_TICKS(5)` = 0 ticks at 100 Hz, so it spun on the single core
|
||||
(task watchdog: IDLE starved). Now waits at least one tick.
|
||||
6. The phone clock is ~14 min fast; GnssTimeSource fell back to it whenever GNSS time blinked out
|
||||
indoors, so every transmitted timestamp (CAM generationDeltaTime too) jumped 14 min back and
|
||||
forth. It now keeps the last measured error.
|
||||
|
||||
Watch COM3 (`idf.py -p COM3 monitor`, or `readlog.py`-style with DTR/RTS low) during these; it only
|
||||
resets the board, the phone is on the other port.
|
||||
|
||||
- [x] **USB session.** Settings > Connection > ESP32-C5: link USB-C, transmit CAM, signing on.
|
||||
Phone on the native port, Connect. Expected: the card shows "Provisioning the demo credentials"
|
||||
once, then Connected and `Signing on · tickets 1 · signed N` with N rising while recording.
|
||||
COM3: `radio on channel 180, transmit and receive`, `tx power: … dBm`,
|
||||
`credentials provisioned: 1 roots, 1 authorities, 1 tickets`, and no `radio refused a frame`.
|
||||
Confirmed by the user 2026-09-23: connects, signing works.
|
||||
- [x] **Reception intact.** Same session, sim car (COM8) beaconing: its CAMs (station 195936478) on
|
||||
the V2X map at ~3 Hz as before. Then put a DENM and a SPATEM on air: both show up (they come
|
||||
through the raw V2X_RX path; the vanetza stack drops them because they are not demo-signed).
|
||||
Confirmed 2026-09-23: sim car and the RSU's CAM/SPATEM/MAPEM arrive; DENM not yet re-tested.
|
||||
- [x] **Signed CAM on air** (2026-09-23, CAM pinger over BLE, signing on). Recorded 25 s through
|
||||
the V2X2MAP bridge's `/api/record` (`micrOBU_workspace/v2x-obu-esp32c5/signed-cam-check.pcap`)
|
||||
and checked with the new `obu-firmware/test/verify_signed_pcap.py` (asn1tools + OpenSSL, no
|
||||
vanetza code): 12/12 secured CAMs, station 999999, psid 36, signer = full certificate of the
|
||||
demo AT `B80B49387A4C12EB`, **all signatures valid**, COER canonical, and the bundle's chain
|
||||
(AT <- AA <- root) verifies. The CiT One (192.168.40.201) also receives them (~1 Hz on
|
||||
`v2x/rx/cam`), i.e. a third-party stack unwraps our 1609.2 envelope; its MQTT API exposes no
|
||||
security fields, and it forwards unsigned and unknown-root messages alike, so it cannot say
|
||||
whether it verified them. The same capture showed generationTime wobbling by seconds, with
|
||||
`time_regression` still firing: fixed in Esp32Link (the PoTi never moves the micrOBU's clock
|
||||
back except for a >= 60 s correction). Re-check: no "restarted its stack" lines in logcat.
|
||||
- [x] **Unsigned toggle.** Signing off: the same capture shows next header 1 (common header), as
|
||||
the previous firmware sent. The card's `signed` count stops rising.
|
||||
Confirmed 2026-09-23: unsigned pinger CAMs show on V2X2MAP as unsigned.
|
||||
- [x] **Signed VAM on V2X2MAP.** Since 2026-09-23 17:16 the COM10 bridge is the colleague's
|
||||
v2x2map-0.3.0 from source with a new `verify.py` and `--trust demo-chain.vcr` (launcher:
|
||||
`micrOBU_workspace/v2x-obu-esp32c5/start-v2x2map-signed.bat`, replacing its-g5-bridge.exe).
|
||||
Signed CAMs from the pinger already show "signature verified" live. Switch to VAM with signing
|
||||
on: the VAM must be decoded (cyclist, position) and show "signature verified" too.
|
||||
Confirmed by the user 2026-09-23: signed VAMs decode and verify.
|
||||
- [x] **VAM.** Transmit VAM: BTP port 2018, psid 638; with `microbu-esp32c5/tools/wireshark/psid-vru.lua`
|
||||
Wireshark decodes the VAM (stationType cyclist, bicyclist profile in every ~2 s VAM). Rate:
|
||||
≥1 per 5 s standing still, about one per GNSS fix while riding.
|
||||
Covered by the V2X2MAP check above (decoded VAM, psid 638); Wireshark not needed.
|
||||
- [x] **RX without recording.** Connect only (no recording, no pinger): sim-car CAMs appear and
|
||||
the RX-queue drop counter stays at 0 or near it.
|
||||
Confirmed 2026-09-23: messages come in on connect alone.
|
||||
- [ ] **No time_regression.** Record for a few minutes standing still indoors: no "refused" line on
|
||||
the card, and COM3 never logs `ITS time moved back`.
|
||||
- [x] **BLE after the NVS fix.** First forget micrOBU-4AFA in Android's Bluetooth settings (the
|
||||
phone still holds the bond the board lost). Then Connect, passkey 123456 once; a second
|
||||
Connect after an app restart must not prompt again, and COM3's next boot must say
|
||||
`1 bonded phone(s) in NVS`.
|
||||
Confirmed 2026-09-23: pairs once, reconnects after an app restart.
|
||||
- [x] **BLE.** Link Bluetooth, unplug USB, Connect. Android asks to pair with micrOBU-4AFA:
|
||||
passkey 123456. Expected: Connected, CAMs keep going, sim-car CAMs keep arriving.
|
||||
While USB is plugged in and in use, the phone's BLE scan must not see micrOBU-4AFA
|
||||
(COM3: `USB link in use: BLE advertising paused`). If it loops again, the card now says why;
|
||||
"refused this phone's stored pairing" means forget micrOBU-4AFA in Android and pair again.
|
||||
COM3 shows `encryption change status=...` for the board's side.
|
||||
Confirmed 2026-09-23: CAMs and VAMs out, reception in, over BLE.
|
||||
- [ ] **BLE/ITS-G5 coexistence (the unmeasured risk from the hardware review).** With BLE
|
||||
connected, count the sim car's CAMs received per minute and ours at the sniffer; compare
|
||||
with the same over USB. A clear drop, or reception stopping altogether, means the coex
|
||||
arbiter takes the radio off 5900 MHz (our channel is set behind the driver's back with
|
||||
`phy_change_channel`). Then BLE cannot be used while receiving, or needs a longer connection
|
||||
interval.
|
||||
- [ ] **Board reset recovery over BLE.** Press RST mid-session: the app reconnects by itself and
|
||||
reconfigures on the first STATUS saying `not configured`, with no manual Connect. (Over USB a
|
||||
reset re-enumerates the port and needs a manual Connect, as before.)
|
||||
|
||||
### Confirm the RX queue drop counter explains the bench-session frame drops / map flicker (added 2026-09-22)
|
||||
|
||||
Investigated the user's report of "OBU mode keeps dropping a few frames" and "v2x screen comes
|
||||
|
||||
Reference in New Issue
Block a user