UI:
- Top bar shows a USB glyph reflecting the serial link on the ESP32-C5 path,
instead of a Wi-Fi glyph driven by an MQTT state that is permanently
disconnected there.
- Recording screen's OBU stream row follows whichever transport the selected
hardware uses. It previously read as offline throughout a recording that was
actively beaconing CAMs.
- Live map uses distinct markers: a centred dot for own position (a fact about
the viewer, not a tracked object) and a teardrop pin for remote stations,
tinted by alert severity. Both were osmdroid's identical default pin before,
and severity required tapping a marker to read its label.
- Sensor Monitor moves out of the bottom nav to Settings > Developer. A live
phone-sensor feed is a bench tool; the Dashboard already reports GNSS/IMU
health. Screen and route are unchanged, just not in the rider's way.
Detection engine on the ESP32 path:
- Seed our own StationID from the persisted value CamTransmitLoop transmits.
It was null here (the CiT One learns it from v2x/rx/obu_gnss, which doesn't
exist on this path), so the self-heard-TX filter never fired: the ESP32 runs
promiscuous for raw TX to work at all, hears our own CAMs back off the air,
and they were tracked as a remote station - a ghost vehicle on top of the ego
position, fed to the engine as a collision partner for itself.
RSSI:
- The firmware has always sent per-frame RSSI in byte 0 of every CAM_RX frame;
the app discarded it. Now carried on Cam, persisted per V2X message, shown per
station in the received-CAM list, and exported. Null for own CAMs and the
whole CiT One path, neither of which has a measurement.
Trips, CSV and export (schema v3 -> v4):
- trips.sessionId links a trip to the CSV session recorded alongside it. The two
are written by independent subsystems that the Recording button happens to
start together; without the link, deleting a trip orphaned its CSV forever.
Timestamp matching was rejected - close recordings would delete the wrong file.
- Deleting a trip now removes the CSV file AND its sessions row, so it stops
appearing in the Session Log pointing at nothing.
- Per-trip combined CSV export: GPS track, detected events, V2X messages (with
RSSI) and the raw sensor samples in one file, keyed by a leading type column.
One file rather than a zip of tables because the point of the export is
correlating those streams, and splitting them pushes the join downstream.
- Export takes the Activity context. Sharing from the ViewModel's Application
context threw AndroidRuntimeException on startActivity - this crashed on the
first tap of the share button.
Trips recorded before v4 have a null sessionId, so their exports omit raw sensor
rows and their CSVs still need clearing by hand once.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>