obu-firmware builds against the vanetza-idf C-ITS library, which until now came from the colleague's microbu-esp32c5 tree beside the repository and was not tracked here, so a clone of this repository could not build the firmware it ships. The library alone is now part of obu-firmware, as obu-firmware/external/vanetza-idf: their external/vanetza-idf at commit cf4b99f, unchanged (9775 files; see its PROVENANCE.md). CMake takes it from there by default; -DVANETZA_IDF_DIR still points the build elsewhere. The rest of the colleague's tree (their own VAM firmware, PKI tooling, station-link Python tools, the V2X2MAP bridge) stays out of this repository and gitignored; nothing is pushed to their repository. NOTES.md, docs/06, TODO.md and the pcap verifier's usage line point at the new location.
4.5 KiB
obu-firmware
Since 2026-09-23: signed ITS on vanetza-idf
This firmware is a port of the colleague's standalone ESP32-C5 VRU station
(microbu-esp32c5/firmware, in their own repository; only its external/vanetza-idf is copied
here, to obu-firmware/external/vanetza-idf).
From it: the vanetza-idf C-ITS stack (BTP, GeoNetworking, the TS 103 097 security entity with
credentials in NVS), the station-link protocol v1 (link_protocol.*, link_service.*) over the
native USB port (serial_link.*, frame type 0x10 in the same 0xAA55 framing as before) and over BLE
GATT (simple_ble.*), and the radio adapter (c5_radio.*, otm_tx_custom.c). Build with ESP-IDF
6.0.2; see FLASHING.md.
The phone builds CAM or VAM, configures the station, provisions credentials, sends PoTi and hands
each message over as a BTP-DATA.request; the firmware adds GN/BTP, signs with the authorization
ticket, and transmits. The phone side is Esp32Link.kt in the app.
Changed or added for this project (search for MicrOBU: in the sources):
- Reception stays as it was. vanetza-idf decapsulates with
itsGnSnDecapResultHandling = STRICT, so it drops unsigned traffic (the bench sim car) and everything signed under a root other than the provisioned demo root (every RSU). Every captured frame therefore also goes through the previous firmware'sgn_unwrap.cand reaches the phone as link opcodeV2X_RX(0x85), whose body is exactly the oldSERIAL_MSG_V2X_RXpayload (Station::forward_raw). The app's receive side is unchanged. - Unsigned transmission is still possible. The colleague's station refuses unsecured requests.
Here a request with GN security profile 1 goes out with the previous firmware's
geonet.cheader and the position of the last PoTi (Station::unsecured_request); the app's "Sign outgoing messages" setting decides per message. - Console on UART0. ESP_LOG stays on the CH343 bridge port (COM3 on the bench); the native port
carries only link frames. The colleague's single-port board routes the log into LOG frames there
(
CONFIG_MICROBU_LOG_OVER_LINK, off here). - BLE pauses while USB is in use (
CONFIG_MICROBU_BLE_USB_IDLE_MS, 3 s): BLE and ITS-G5 share the C5's one RF front end. Whether a live BLE connection disturbs 5.9 GHz is still unmeasured (TODO.md). - A serial write no longer stalls the station task when no USB host is present (BLE-only use).
- A notification longer than the ATT MTU is dropped instead of silently truncated.
- The Wi-Fi RX callback's 2.4 KB capture buffer is static rather than on the driver task's stack
(the previous firmware's commit
04b0076fixed the same risk). - Manual country policy and the TX-power read-back from the previous firmware's radio bring-up.
- The activity LED (GPIO27 on the colleague's XIAO board) is off unless configured.
Credentials: the app ships assets/demo-chain.vcr, a throwaway chain generated 2026-09-23 with the
colleague's vidf_issue (root 6E7D0374FB021901, AA B3312F29844299E0, AT B80B49387A4C12EB
valid two years, permissions psid 36 SSP 010000 and psid 638 SSP 01). The colleague's own demo
chain only grants psid 638 and so cannot sign CAMs. Not EU-registered: receivers that verify against
the EU trust list drop what it signs.
Time: the signature's generationTime comes from the PoTi timestamp, which follows the app's
ItsTime convention (UTC-based, no leap seconds). The colleague's VBS adds the 5 leap seconds.
Which one is right is the open question documented in ItsTime.kt.
Earlier notes (Phase 2, superseded)
OBU transmit firmware - Phase 2 (in progress: HLN-SV DENM beacon)
Started. See docs/04-transmit-setup.md in the project root for build/flash
steps and how to validate this against your own sniffer.
Implements one profile so far: HLN-SV (aftermarket stationary recovery vehicle), causeCode 94 (stationaryVehicle), subCauseCode 0, active while the hazard-light GPIO is grounded. No location/alacarte containers.
main/main.c- entry point, thephy_11p_set/phy_change_channel(5900,...)register hack, GPIO polling, TX loopmain/denm.c/.h- ASN.1 UPER encoding of a minimal DENMmain/geonet.c/.h- GeoNetworking Basic/Common/SHB headers + BTP-Bmain/dot11p.c/.h- 802.11 OCB (QoS Data, broadcast) frame + LLC/SNAP
Known gaps, tracked as TODOs in the source: no real GNSS (lat/long hardcoded 0), no real time source (detectionTime/referenceTime hardcoded 0, decodes as 2004-01-01), fixed (non-rotating) pseudonym MAC, SHB instead of GeoBroadcast (no multi-hop forwarding), unsecured (no IEEE 1609.2 signing).