feat: Drive Mode HUD, OTM Live Feed, PCAP Upload, Demo Mode & UI overhaul (v0.3.0)#4
Open
studio-justin-braun wants to merge 2 commits into
Open
feat: Drive Mode HUD, OTM Live Feed, PCAP Upload, Demo Mode & UI overhaul (v0.3.0)#4studio-justin-braun wants to merge 2 commits into
studio-justin-braun wants to merge 2 commits into
Conversation
Add a version badge and detailed 0.3.0 release notes to the README. Document new features including Drive Mode (experimental HUD), OTM Live Feed (WebSocket), PCAP upload, Demo Mode, and UI overhaul; update the Features table and architecture diagram text to reflect these additions. Add a Changelog section (0.3.0 and 0.2.3) noting Gradle 8.9/Java 21 compatibility and OkHttp dependency. Small formatting and layout tweaks throughout the file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds four major new features to the Android app, a full UI overhaul and
several bug fixes. All changes are backwards-compatible — existing settings,
recordings and MQTT configurations are preserved.
New Features
🚗 Drive Mode (experimental)
A full-screen animated driving HUD that replaces the map while in motion.
Activated via a new car-icon mini FAB in the main screen.
What it does:
DriveViewCanvas (no bitmaps,fully programmatic drawing). Road animation speed is proportional to real
GPS speed.
is within 300–400 m ahead (bearing cone ± 90°). Shows live R/Y/G phase,
countdown in seconds and distance. Data is sourced from both hardware SPATEM
frames and the OTM WebSocket simultaneously.
red outlines with headlight glow for oncoming traffic (150–210°), and a badge
indicator for close-following vehicles (< 70 m behind).
within 500 m in the direction of travel.
exit (unless the user had already enabled it manually).
ConstraintSetwhen active so itremains accessible in the bottom-right corner over the full-screen view.
New files:
DriveView.kt,ic_drive.xml📡 OTM Live Feed
Streams live V2X data from
wss://opentrafficmap.org/ws_ext?gzip=truedirectlyonto the existing OSMDroid map layer.
Implementation:
OtmWebSocketClient.kt— OkHttp WebSocket with gzip decompression,exponential back-off reconnect (2 s → 30 s) and main-thread callback delivery.
delta— incremental updates via top-levelupsertPoints[]snapshot— full state dump viapoints.features[](different structure!)traffic-light-map-batch— static MAPEM intersection positions used topre-populate the traffic light cache before live SPAT data arrives
OtmLiveLayer.kt— separate map overlay with per-entity marker management,bounding-box filtering (±10 % of visible area, max 50 km) and
refilter()onscroll/zoom events.
#FF8F00for vehicles,#00BFA5for traffic lights,etc.) makes OTM markers instantly distinguishable from locally received frames.
OtmPoint.ktdata class;spatSecsLeftfield carries countdown seconds.Dependency added:
com.squareup.okhttp3:okhttp:4.12.0New files:
OtmWebSocketClient.kt,OtmLiveLayer.kt,OtmPoint.kt,ic_live.xml📤 PCAP Upload
Replays locally recorded
.pcapfiles to any configured MQTT broker — offline,without the ESP32-C5 hardware. Mirrors the Python
pcap-replay.pyworkflow.Implementation:
PcapUploadActivity.kt— lists allitsg5-*.pcapfiles fromgetExternalFilesDir()sorted newest-first. Reads standard libpcap format(magic
0xa1b2c3d4LE, 24-byte global header, 16-byte per-packet headers).PcapFileAdapter.kt—ListAdapter<File>with DiffUtil, shows filename,date and human-readable size.
lifecycleScopeonDispatchers.IO; progress is reported backto the main thread with a bottom card overlay (filename,
LinearProgressIndicator,packet counter, cancel button).
MqttBridgewith a-upload-Nclient-ID suffix to avoid broker-levelconflicts with the live MQTT bridges already running in MainActivity.
menu_main.xml).New files:
PcapUploadActivity.kt,PcapFileAdapter.kt,activity_pcap_upload.xml,item_pcap_file.xml,ic_upload.xml🛠 Demo Mode (DevOps)
Generates structurally valid ITS-G5 frames in the current map viewport for
testing without hardware. Toggled from About → DevOps.
Implementation:
DemoFrameGenerator.kt— coroutine-based generator (300 ms tick onDispatchers.Main). Creates 7 simulated vehicles and 2 SPATEM RSUs aroundthe map centre.
802.11 MAC (24 B) + LLC/SNAP (8 B) + GN Basic (4 B) + GN Common (8 B) + SHB LPV (28 B) + BTP-B (4 B) + app stub (10 B) = 86 bytes.ItsG5Decoder.decodeFull()extracts all fields correctly (lat/lon, speed,heading, station ID, message type).
handleFrames()pipeline as hardwareframes: PCAP recording, MQTT forwarding, frame log, MarkerLayer, GeigerCounter
and SPAT light indicator all work on demo data.
0x00FF_0000_0000prefix so recordings can be identifiedas synthetic.
away. RSUs cycle RED (50 ticks) → YELLOW (10) → GREEN (60).
SettingsBus.demoModeActiveflag survives Activity recreation.New files:
DemoFrameGenerator.ktUI / Design Overhaul
Settings screen
All sections are now wrapped in
MaterialCardView(colorSurfaceContainerHigh,16 dp corner radius, 0 dp elevation) providing clear visual separation between
unrelated groups of controls. Previously everything was a flat scrollable list.
Main screen
btnConnect,btnConnectBt): addedcolorSurfacebackground#BB000000background with
@drawable/bg_overlay_rounded(semi-transparent, 10 dpcorner radius).
elevation=3dp,letterSpacing, monospace stats text.emptyLogalpha reduced to 0.45 for better contrast against the map.Styles
Section.Header: addedletterSpacing="0.1"andpaddingStart="4dp".@style/SettingCardfor reusable card containers.Bug Fixes
OtmWebSocketClientspeedKmh: nullcrash —getDouble()throws on JSON null; replaced withoptDouble(…, NaN).takeUnless { it.isNaN() }OtmWebSocketClientpoints.features[]notupsertPoints[]; parser now falls back correctlyOtmWebSocketClientkind: "traffic_light"(underscore); normalised with.replace('_', '-')OtmWebSocketClientminEndTime/timeStampare DSRC TimeMarks in milliseconds within the current minute (0–59 999); corrected formula:((endMs − tsMs + 60 000) % 60 000) / 1 000OtmWebSocketClienttraffic-light-map-batchcompletely ignored — addedparseMapBatch()to pre-populate traffic light positions from MAPEM dataAboutActivitybindingwas a local variable inonCreate;updateDemoButton()outsideonCreatecausedUninitializedPropertyAccessException— promoted toprivate lateinit varfabDriveModeoverlappedfabLocatedue to wrongConstraintSetanchor (bottom_toTopOf=logSplit); fixed by placing it abovefabOtmLivein chain, repositioned dynamically viaConstraintSetwhen drive mode is activeDriveViewonly filled 70 % of screen —logSplitguideline not moved to 1.0f; fixed intoggleDriveMode()MqttBridgeclientIdSuffixparameter to avoid MQTT broker-level client-ID conflicts between live bridges and upload bridgesgradle-8.4incompatible with Java 21 — upgraded togradle-8.9Files Changed
Testing
cits1.opentrafficmap.orgCompatibility
INTERNETpermissionTested on Android 16 (API 36.1) emulator and physical devices running Android 13/14.
All feedback on Drive Mode real-world behaviour is very appreciated — please open an issue or comment here.