c13c3891c95476000d84841d1f37c7d9c709be22
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a08494b56a |
Drive the ESP32-C5 station over USB or BLE, send CAM or VAM, signed or not
The app now speaks the station-link protocol of the new obu-firmware. Esp32Link picks the transport from Settings (UsbSerialTransport or the new BleLinkTransport), tells the previous firmware from the new one by its heartbeat, and runs the session: STATION_CONFIGURE with the current pseudonym MAC (which also starts the board's radio), CREDENTIALS_PROVISION of the bundled demo chain when the board has no ticket, then per message a POTI_UPDATE and a BTP_DATA_REQUEST. Received messages still arrive as V2X_RX frames, so the receive side is unchanged. A board on the previous firmware keeps working for CAM over USB. Settings > Connection > ESP32-C5: link USB-C or Bluetooth, transmit CAM or VAM, "Sign outgoing messages" (on by default). The connection card, top bar and dashboard show the link in use, the pairing passkey and signing counters. - VAM: VamUperCodec (TS 103 300-3 V2.3.1, bytes checked against asn1tools) and VamGenerationRules (clause 6.4, Tables 16/17). - BLE: the firmware's GATT layout (service 0000C175-...), MTU 517, pairing and encryption settled before any other operation (short timeouts during pairing made it loop), backoff between attempts, reasons on the card. - Clock: a PoTi goes to the board once per new fix and never moves the board's clock backwards except for a real correction (>= 60 s); stale and wobbling fix times made the board answer time_regression and restart its stack every few seconds. GnssTimeSource keeps the last measured phone-clock error while GNSS time drops out indoors: the bench phone is 14 minutes fast, and falling back to it made every transmitted timestamp jump by that much. - assets/demo-chain.vcr: throwaway, not EU-registered demo chain generated 2026-09-23 (AT B80B49387A4C12EB, psid 36 and 638). Its private key ships with the app on purpose; receivers verifying against the EU trust list drop what it signs. - Bluetooth permissions requested at start-up on Android 12+. StationLinkTest pins the codec to bytes from the colleague's Python implementation (microbu_link/messages.py). 103 unit tests pass. |
||
|
|
83153a0971 |
Send each CAM with its position vector, a rotating pseudonym and GNSS time
The app side of the firmware's CAM_TX_PV message. Until now the phone handed the ESP32 bare CAM bytes, so the GeoNetworking header around them could only carry the firmware's bench placeholders. GnPositionVector.fromCam builds the Source Position Vector from the same Cam the UPER is encoded from, so the two layers cannot disagree about where the rider is. Position is rounded exactly as CamUperCodec rounds it, heading wraps into 0..3599, and non-finite values become 0. PAI is set when Android's horizontal accuracy is at most 24.7 m, the 40 m itsGnPaiInterval/2 threshold converted from a 95% to a 68% confidence radius. UsbSerialTransport.sendCamTx sends 0x05 once the heartbeat advertises the capability and 0x01 otherwise, so this build still transmits against older firmware, and logs which path it is on. Pseudonyms. The station ID used to be created once per install and never changed, under a MAC that never changed either, so every CAM this phone ever sent was linkable to every other. PseudonymManager now owns the station ID and the MAC as one identity and replaces both together every 10 minutes, or immediately if the clock goes backwards. Both are persisted in a single edit, so a crash cannot leave them mismatched. MACs are locally administered unicast and can never equal the bench ping's. CamTransmitLoop takes the current pseudonym per CAM, and the two most recently retired IDs still count as ours, so a frame sent just before a rotation is not taken for a stranger. GNSS time. On 2026-09-10 the bench phone's clock was 24 minutes fast: with no SIM and no internet time it had no automatic time source, and every CAM went out stamped in the future. GnssTimeSource moves transmit timestamps onto SystemClock.currentGnssTimeClock() and falls back to the wall clock without a fix, logging which one is in use and the measured error. ItsTime is now the single rule for both the CAM's generationDeltaTime and the GN TST. Receive paths stay on the wall clock so everything they stamp remains comparable. The bench pinger keeps its fixed station 999999 and a fixed MAC, so a ping stays recognisable in a capture. 999999 now counts as ours only while this phone's pinger runs and for 5 s after it stops. The previous rule treated it as ours unconditionally, which hid another phone's pings on the same bench. Leap seconds are an open question, recorded in ItsTime: TimestampIts may be TAI-based, which would put it 5 s higher. 85 tests, 0 failures. |
||
|
|
b91eb460dc |
Phase 03: CAM decode coverage, real sensor data in TX, V2X monitor for ESP32 path
CAM codec: - Stop rejecting CAMs carrying a specialVehicleContainer. It is declared last in CamParameters, after everything this decoder reads, so buses / emergency vehicles / road-works vehicles now decode for position and kinematics instead of being dropped outright - Drop the lowFrequencyContainer parse - it extracted nothing into Cam, and its reads were only correct when no high-frequency optionals were present - Document why the 7 optional-presence bits are consumed but not acted on: UPER writes a SEQUENCE's presence bitmap up front but each field's value in declaration order, and all seven are declared after yawRate - Field widths and container ordering verified against the ETSI ASN.1 sources in the C-ITS-Parser checkout, not from memory Transmit path: - Own StationID is now a persisted random 32-bit value instead of a hardcoded 0. Receivers key on StationID to track a station across CAMs, so every unit broadcasting 0 made two MicrOBUs indistinguishable - including to this app's own detection engine - Populate longitudinalAcceleration from successive GNSS speed samples. Not from the accelerometer: CAM wants signed along-track acceleration, and the raw sensor is device-frame with gravity in it. Null outside a usable sample gap rather than a fabricated value - CAM pinger builds from live GNSS/IMU via PhoneCamBuilder instead of beaconing a hardcoded bench coordinate with speed and heading pinned to zero, so it now exercises the sensor pipeline and not just the wire. Sends nothing without a fix, and reports that rather than sitting at "Sent: 0" V2X monitor: - Received-CAM pane for the ESP32-C5 path, replacing the MQTT topic list that is permanently empty there. One row per station rather than per message - CAMs arrive at 1-10 Hz per station, so the pane is bounded by road users nearby, not by traffic rate. Nearest first, tinted by active alert level - DENM hazard pins on the live map as a warning triangle, drawn above vehicle markers. CiT One path only: the ESP32 firmware forwards BTP-B port 2001 (CAM) and drops port 2002 before it reaches the phone DenmParser uses tolerant field-name matching - the Use Case API's DENM JSON schema is not yet confirmed against real payloads. |
||
|
|
33c4ec5998 |
Phase 03: real CAM UPER codec + ESP32-C5 TX/RX serial link
- Firmware: rewrite obu-firmware TX loop to be serial-driven (no on-chip timer), add promiscuous RX + GeoNetworking/BTP unwrap (gn_unwrap.c), add binary UART framing to the phone (serial_link.c/.h). Drop local cam_encode() - CAM is now built on the phone. - Kotlin: byte-exact UPER CAM encoder/decoder ported from cam.c (BitWriter/BitReader/CamUperCodec), matching SerialFrame codec, real UsbSerialTransport (usb-serial-for-android), CamTransmitLoop (1Hz base rate, event/geofence boost, ESP32-C5-only), wired into CamUseCaseRepository for RX and TripRecordingService for TX. - Add V2X message retention: persist all CAM (own+remote) to Room while recording, drop otherwise (DB v2 -> v3 migration). - Add jitpack repo + usb-serial-for-android dependency. Fixes: UsbSerialTransport now uses SerialInputOutputManager.start()/stop() (this lib version manages its own thread internally) instead of manual Runnable/Thread submission, which didn't compile. |