Files
MicrOBU/README.md
T

158 lines
11 KiB
Markdown
Raw Normal View History

2026-06-08 16:23:08 +02:00
# MicrOBU Android App
Android companion app for the micrOBU; a compact V2X on-board unit developed by HAW Hamburg and consider it GmbH for vulnerable road users (cyclists, e-bike riders, pedestrians).
The app is the HMI for the OBU hardware and, on one of the two supported hardware paths, the entire V2X protocol stack. It handles V2X message display, use case detection, sensor collection, trip recording, and OBU communication over USB-C.
2026-06-08 16:23:08 +02:00
**Platform:** Android (Kotlin) / **Min SDK:** 29 (Android 10) / **Target SDK:** 36 / **Version:** 0.5.0 (Phase 03)
## Project goal
Demonstrate V2X communication with at least one C2C-CC bicycle safety use case working on the ESP32-C5, specifically intersection movement assist: a car approaching an intersection on a path that conflicts with the rider's.
That use case is driven entirely from the periodic position and kinematics vehicles broadcast. It needs no traffic light state and no intersection lane geometry, which is why several scope decisions in this repository look deliberately narrow.
## Two hardware paths
The project began against the consider it CiT One and later added the ESP32-C5 as a second option. Both paths are supported at runtime and selected by the rider in Settings > OBU Hardware.
| | consider it CiT One | ESP32-C5 |
|---|---|---|
| What it is | Complete V2X on-board unit | Development board acting as a plain radio |
| Transport | IP over USB tethering, MQTT | Framed binary protocol over USB CDC serial |
| Reaches the phone as | Processed JSON | Raw ASN.1 UPER bytes |
| V2X stack lives | On the OBU | On the phone, except the radio and GeoNetworking |
| Own CAM generated by | The OBU, autonomously | The phone, transmitted on the phone's clock |
| DENM trigger | Available (manual test tool) | Not available |
| Needs a network | Yes, internally | No |
Both paths converge at `CamUseCaseRepository`, which normalises whatever arrived into the domain `Cam` type. Everything above that point, including the entire use case detection engine and all UI, is shared and transport-agnostic. That is what makes the ESP32-C5 a drop-in second OBU rather than a fork of the application.
2026-06-08 16:23:08 +02:00
## What it does
**Real-time V2X monitoring**; live CAM, DENM and SPATEM with a station list, active hazards, live signal phase, and a map view. On the CiT One path the topic viewer additionally shows whatever the broker publishes, grouped by topic with pretty-printed JSON and TX/RX badges.
2026-06-08 16:23:08 +02:00
**CAM-based use case detection**; correlates the rider's own state with a short per-station history of received CAMs to evaluate five C2C-CC bicycle safety use cases (IMA-B, IMA-S, RTW-B, LTW-B, SMVA/BCW-B) and raises alerts under the three-tier Info / Awareness / Warning model. None of these use cases generates a DENM.
2026-06-08 16:23:08 +02:00
**Phone-generated CAM**; on the ESP32-C5 path the app builds a CAM from live GNSS and IMU, UPER-encodes it, and pushes it down the serial link for the board to broadcast over ITS-G5.
**DENM transmission**; CiT One path only. Triggers the stationary vehicle profile (`hln-sv`, causeCode 94) via the consider it Use Case API. This is a manual antenna and range test tool. It is never triggered by a detected event or a use case alert, and the control is hidden entirely on the ESP32-C5 path.
2026-06-08 16:23:08 +02:00
**Trip recording**; foreground service records all sensor streams and detects cycling manoeuvres (braking, turning, stopping) using orientation-independent signal processing. Works fully offline with no OBU connected. The detected manoeuvres are not shown in the app - they raise the CAM transmit rate through the manoeuvre on the ESP32-C5 path, and are kept in the trip's CSV export for offline analysis.
2026-06-08 16:23:08 +02:00
**Trip review**; past trips displayed as a route on an OpenStreetMap layer, with duration and distance.
2026-06-08 16:23:08 +02:00
**CSV export**; every sensor sample written to a timestamped CSV in real time. Trip exports additionally include the V2X messages received and their RSSI. Shareable via the standard Android share sheet.
2026-06-08 16:23:08 +02:00
## Architecture
MVVM with Repository pattern throughout. Jetpack Compose for all UI (no XML layouts). Hilt for dependency injection.
```
ui/screens/ Compose screens (Dashboard, Record, Trips, V2X Monitor, Settings...)
2026-06-08 16:23:08 +02:00
ui/navigation/ Navigation graph and bottom nav bar
viewmodel/ MqttViewModel, SensorViewModel, TripRecordingViewModel
data/mqtt/ MQTT repository, Paho client, exponential-backoff reconnection
data/transport/ UsbSerialTransport, SerialFrame, UsbNetworkDetector, ObuHardware
data/cam/ CamUseCaseRepository; where both hardware paths converge
data/db/ Room database (sessions, trips, detected events, V2X messages)
data/ SensorRepository, TripRepository, CsvExporter, TripExporter
domain/asn1/ BitReader/BitWriter and the CAM, DENM and SPATEM UPER codecs
domain/usecase/ UseCaseDetectionEngine, UseCaseDetectionConfig, AlertLevel, GeoMath
2026-06-08 16:23:08 +02:00
domain/detection/ EventDetector, RunningStats sliding window (orientation-independent)
domain/cam/ Cam, CamParser, PhoneCamBuilder, CamTransmitConfig
service/ TripRecordingService, CamTransmitLoop, CamPinger
obu-firmware/ ESP32-C5 firmware (serial link, GeoNetworking, 802.11 OCB, raw TX)
asn1/ Vendored ETSI ASN.1 modules the codecs are verified against
2026-06-08 16:23:08 +02:00
```
The `domain/` packages contain no Android imports. That is what makes the 41-test JVM suite possible without an emulator or instrumentation.
2026-06-08 16:23:08 +02:00
## Connectivity
USB-C on both hardware paths. Bluetooth is **not implemented** and remains an open question in the requirements.
2026-06-08 16:23:08 +02:00
| Transport | Path | Status |
|---|---|---|
| USB-C tethering (IP + MQTT) | CiT One | Active |
| USB-C serial (framed binary) | ESP32-C5 | Active |
| Wi-Fi | CiT One | Developer builds only |
| Bluetooth | Either | Not implemented |
2026-06-08 16:23:08 +02:00
On the CiT One path the MQTT broker runs on the OBU (Mosquitto 2.0.11, port 1883); Android USB tethering exposes it as a virtual Ethernet interface at `192.168.42.x` and the app auto-detects the gateway IP on plug-in. On the ESP32-C5 path there is no network layer at all: a private framed protocol runs over the board's native USB-C port as a CDC-ACM device.
## Verification
The app hand-encodes and decodes ETSI messages bit by bit on the ESP32-C5 path, which is the highest-risk code in the project. Round-trip tests through the project's own codecs structurally cannot catch a shared mistake about a field's bit width, and this project shipped exactly that bug three times (`CurvatureCalculationMode`, the GeoNetworking reserved bytes, `yawRateConfidence`). Phone and ESP32 agreed with each other and with nothing else.
Verification therefore uses an independent oracle: `asn1tools` compiled from the ETSI modules vendored in `asn1/`.
- **Golden-byte fixtures** assert exact encoder output, with expected values produced by the oracle rather than by this encoder.
- **Bulk replay** compares every field over real captures: 79,042 SPATEMs and 1,885 DENMs, zero mismatches.
- **Off-air confirmation**: 26 of this project's own CAMs captured back by an independent receiver, all accepted.
Never regenerate a golden fixture from this project's own encoder output. See `asn1/README.md`.
## Documentation
| Document | Audience |
|---|---|
| [docs/MicrOBU-User-Guide.docx](docs/MicrOBU-User-Guide.docx) | Riders. Setup, screens, what the alerts mean, troubleshooting |
| [docs/MicrOBU-Technical-Documentation.docx](docs/MicrOBU-Technical-Documentation.docx) | Supervisors and stakeholders. Architecture, message path, verification, results, decisions |
| [docs/01-requirements-traceability.md](docs/01-requirements-traceability.md) | Requirements chapters 0 to 13 mapped to implementation and evidence |
| [05-obu-bench-test-2026-08-25.md](05-obu-bench-test-2026-08-25.md) | Bench campaign T1 to T9, measured results |
| [04-transmit-setup.md](04-transmit-setup.md) | Transmitter bring-up, radio configuration diagnosis, the TX bypass |
| [obu-firmware/FLASHING.md](obu-firmware/FLASHING.md) | Toolchain setup, flashing, phone-to-board bring-up checklist |
| [asn1/README.md](asn1/README.md) | ASN.1 module provenance and the fixture regeneration rule |
| [docs/references.bib](docs/references.bib) | Standards references as BibTeX |
2026-06-08 16:23:08 +02:00
## Key dependencies
| Library | Purpose |
|---|---|
| Jetpack Compose + Material3 | UI |
| Eclipse Paho MQTT | CiT One path communication |
| usb-serial-for-android | ESP32-C5 path communication (custom probe table for Espressif VID/PID) |
2026-06-08 16:23:08 +02:00
| Room | Local database |
| Hilt | Dependency injection |
| OSMDroid | Trip review and live V2X map |
2026-06-08 16:23:08 +02:00
| DataStore | Settings persistence |
| FusedLocationProviderClient | GNSS |
## Getting started
1. Open in Android Studio and build the `app` module. Gradle 8.10.2.
2026-06-08 16:23:08 +02:00
2. Connect a device running Android 10+ (API 29).
3. Choose your hardware in Settings > OBU Hardware.
2026-06-08 16:23:08 +02:00
**CiT One path.** Plug the phone into the OBU via USB-C, enable USB tethering on the phone, and the app detects the interface and connects automatically. Broker IP can be overridden in Settings > Connection.
**ESP32-C5 path.** Flash `obu-firmware/` (see `obu-firmware/FLASHING.md`), then plug the phone into the board's **native** USB-C port, not the UART bridge port used for flashing. Tap Connect and grant the USB permission. Use the CAM Pinger on the V2X screen to verify the link and radio without starting a trip.
**Standalone trip recording.** No OBU required. Go to the Record tab and tap REC.
The Wi-Fi transport (broker at `192.168.3.202`) remains available in developer builds via Settings > Developer.
Firmware and app must be flashed and installed together: `SERIAL_LINK_MAX_PAYLOAD` is 512 on both sides and a mismatch silently rejects every large frame.
## Status and known limitations
Bench verified against live ITS-G5 traffic on 2026-08-25: 2868 frames over 305 seconds, zero decode failures, zero USB errors, zero crashes. Not yet road validated.
- **Requirement 11.6, Phase A success criteria, is not met.** The bench proves reception. It cannot prove the use case behaves correctly with two genuinely moving stations, because nothing on the bench moves. This is the main open evidence gap for the project's central claim.
- **No message signing.** ETSI TS 103 097 is out of scope. Secured frames are rejected rather than mis-parsed.
- **Detection thresholds are untuned engineering estimates**, not calibrated against real intersection data.
- **512-byte serial payload cap.** Roughly 70% of real road RSU SPATEMs would be dropped as oversize. Accepted deliberately: the intersection use case is CAM-driven and needs none of it.
- **No automatic reconnect** after USB re-enumeration; requires a manual Connect.
- **Station IDs rotate**, so they cannot identify a physical unit over time.
- **No backend, no login.** Everything is on-device.
- **No MAPEM decoder**, so signal groups cannot yet be associated with the rider's lane.
2026-06-08 16:23:08 +02:00
## Project context
The micrOBU project is funded under the ZIM program (BMWK) and targets micromobility users in Hamburg. The companion app offloads processing from the compact OBU hardware to the smartphone; GNSS fusion, event detection, and on the ESP32-C5 path the full ASN.1 encoding and decoding all run on the phone to keep the OBU lightweight and power-efficient.
2026-06-08 16:23:08 +02:00
V2X communication uses ITS-G5 (IEEE 802.11p) at 5.9 GHz. On the CiT One path the app communicates via the consider it MQTT API v6 (processed JSON). On the ESP32-C5 path the app performs its own ASN.1 UPER encoding and decoding against the ETSI modules vendored in `asn1/`.
2026-06-08 16:23:08 +02:00
**Owner:** HAW Hamburg