Ashin WalpolaandClaude Opus 5 528637dab6 Fix UPER encoding of CurvatureCalculationMode; verified on hardware
CurvatureCalculationMode is the one extensible ENUMERATED in CAM:
  ENUMERATED {yawRateUsed(0), yawRateNotUsed(1), unavailable(2), ...}
UPER encodes an extensible ENUMERATED as an extension bit followed by the root
index - 1 + 2 = 3 bits. All three of our encoders wrote only the 2-bit index,
shifting yawRate and the entire low-frequency container one bit early for any
standards-compliant receiver.

It went unnoticed because every end of this project shared the mistake: the
Kotlin codec was ported bit-for-bit from cam.c, so phone and ESP32 agreed
perfectly with each other and with nothing else. Confirmed against the ETSI
ASN.1 in the C-ITS-Parser checkout, where rasn marks this type - and only this
type - #[non_exhaustive].

Fixed in all three copies of the encoder (app CamUperCodec.kt,
obu-firmware/main/cam.c, obu-cam-transmistter/main/cam.c) plus the decoder,
which now rejects rather than misreads a set extension bit. Frame size is
unchanged at 43 bytes. Transmitter reflashed and the phone decodes its CAMs.

Also in this change:

- serial_link: skip send_frame entirely when no USB host is attached, and raise
  the tx mutex timeout above the worst-case hold. With the phone unplugged every
  write blocked its full timeout while holding the lock, so forwarded CAM_RX
  traffic starved the 1 Hz heartbeat - observed as "tx mutex timeout, dropping
  frame" on the console, and it would have tripped the phone's link watchdog.
  Verified gone on hardware.
- Log decoded and failed CAMs in CamUseCaseRepository. "The app shows nothing"
  had two indistinguishable causes; a silent `?: return` made this bug much
  harder to find than it needed to be.
- Remove the ESP32 send-only/send-and-receive toggle. Reception can't be
  disabled in firmware (raw TX only works while promiscuous), so it was an
  app-side filter pretending to be a radio control.
- V2X monitor follows the serial link state on the ESP32 path instead of MQTT,
  which is permanently disconnected there; CAM intake is gated on the link being
  up, and engine state is cleared when it drops.
- About screen: 0.5.0, Phase 03.
- Track obu-cam-transmistter, the bench CAM transmitter. Its cam.c is compiled
  (unlike obu-firmware's reference copy) and must stay bit-identical to the other
  two - this commit is what that coupling costs when it's broken.
- Document the two-toolchain split: this project builds on IDF 5.5.4, obu-firmware
  on the pinned 6.1. Exporting both in one shell fails confusingly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 14:50:35 +02:00
2026-08-10 11:38:01 +02:00
2026-07-24 11:41:29 +02:00
2026-06-03 14:51:31 +02:00
2026-06-03 14:51:31 +02:00
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 serves as the HMI for the micrOBU hardware, handling V2X message display, sensor data collection, trip recording, and OBU communication over USB-C, Wi-Fi (dev), and Bluetooth (upcoming).

Platform: Android (Kotlin) · Min SDK: 29 (Android 10) · Target SDK: 36

What it does

Real-time V2X monitoring; subscribes to the OBU's MQTT broker and displays live CAM, DENM, SPAT, MAP, and CPM messages grouped by topic with pretty-printed JSON and TX/RX badges.

DENM transmission; triggers DENM use cases (e.g. stationary vehicle warning hln-sv) on the OBU via the consider it Use Case API (v2x-uca/input/denmtrg) with a single tap.

Sensor monitoring; live readout of phone GNSS, accelerometer, gyroscope, magnetometer, and barometer alongside OBU GNSS for cross-reference.

Trip recording; foreground service records all sensor streams and detects cycling events (braking, turning, stopping) using orientation-independent signal processing. Works fully offline with no OBU connected.

Trip review; past trips displayed on an OpenStreetMap layer with detected events overlaid as coloured pins. Tap any pin for event details.

CSV export; every sensor sample written to a timestamped CSV in real time during a session. Shareable via the standard Android share sheet.

Architecture

MVVM with Repository pattern throughout. Jetpack Compose for all UI (no XML layouts). Hilt for dependency injection.

ui/screens/         Compose screens (Dashboard, V2X Monitor, Sensors, Recording, Trip History, Settings…)
ui/navigation/      Navigation graph and bottom nav bar
viewmodel/          MqttViewModel, SensorViewModel, TripRecordingViewModel
data/mqtt/          MQTT repository, Paho client, exponential-backoff reconnection
data/transport/     USB tethering detection and gateway IP resolution
data/db/            Room database (sessions, trips, detected events)
data/               SensorRepository, TripRepository, CsvExporter
domain/detection/   EventDetector, RunningStats sliding window (orientation-independent)
service/            TripRecordingService (foreground service)

Connectivity

The app uses a phased transport strategy. The MQTT client, topic subscriptions, and all UI are identical across transports; only the underlying network path changes.

Phase Transport Status
Phase 01 Wi-Fi Complete
Phase 02 USB-C tethering Active
Phase 03 Bluetooth BLE Future

The MQTT broker runs on the OBU hardware (Mosquitto 2.0.11, port 1883). In Phase 02, Android USB tethering exposes the OBU as a virtual Ethernet interface at 192.168.42.x. The app auto-detects the gateway IP on plug-in.

Key dependencies

Library Purpose
Jetpack Compose + Material3 UI
Eclipse Paho MQTT OBU communication
Room Local database
Hilt Dependency injection
OSMDroid Trip review map
DataStore Settings persistence
FusedLocationProviderClient GNSS

Getting started

  1. Open in Android Studio (Hedgehog or newer).
  2. Connect a device running Android 10+ (API 29).
  3. Build and run the app module.
  4. For Phase 02 testing: plug the phone into the OBU via USB-C, enable USB tethering on the phone, and the app will detect the interface and connect automatically. Broker IP can be overridden manually in Settings → Connection.
  5. For standalone trip recording: no OBU required. Go to the Record tab and tap Record.

The Wi-Fi transport (Phase 01 broker at 192.168.3.202) remains available in developer builds and can be toggled in Settings → Developer.

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 future antenna coordination all run on the phone to keep the OBU lightweight and power-efficient.

V2X communication uses ITS-G5 (IEEE 802.11p / DSRC) at 5.9 GHz. The app communicates with the OBU exclusively via the consider it MQTT API v6 (processed JSON messages); no ASN.1 encoding in the app.

Owner: HAW Hamburg

S
Description
No description provided
Readme
21 MiB
Languages
Kotlin 64.3%
C 19.5%
C++ 12.6%
Python 2.6%
CMake 0.5%
Other 0.5%