The firmware forwarded CAM only: gn_unwrap_cam accepted single-hop broadcast
(HT=5) and BTP port 2001, so every DENM was dropped before it reached the phone.
Real OBUs disseminate DENM by GeoBroadcast (HT=4), whose 44-byte extended header
also carries the hazard's relevance area - materially more useful on a map than
the sender's own position, since a sender may be relaying for someone else.
Firmware
- gn_unwrap_cam -> gn_unwrap_its: accepts GeoBroadcast alongside TSB/SHB, and
BTP ports 2001 and 2002, extracting the GeoBroadcast destination area. Both
extended-header lengths were measured against live air capture rather than
read off a spec table. Secured packets (Basic Header NextHeader=2) are
rejected rather than misparsed.
- SERIAL_MSG_CAM_RX (0x02) superseded by SERIAL_MSG_V2X_RX (0x04): a 14-byte
prefix carrying BTP port, RSSI and the destination area. Adding MAPEM later
needs a decoder on the phone but no protocol change. 0x02 stays reserved so
the numbering is not silently reused.
- Promiscuous RX capture buffer 400 -> 800 bytes. A real GeoBroadcast DENM is
around 500 bytes on air and was being truncated mid-payload, which no amount
of correct unwrapping downstream could have recovered from.
- geonet_wrap_shb, both firmwares: the SHB extended header is 28 bytes, not 24.
The Source Position Vector is followed by a 4-byte reserved field; without it
a standards-strict receiver reads the CAM payload's first two bytes as the BTP
destination port.
App
- DenmUperCodec: UPER decoder for the ManagementContainer and the
SituationContainer's eventType. ValidityDuration is 17 bits, not 16, and
ManagementContainer, SituationContainer and CauseCode each carry their own
extension bit - a single wrong bit made a real frame read causeCode 47
instead of 94.
- DenmEvent gains actionID (originatingStationID + sequenceNumber), stationType,
termination, detectionTime, relevance radius and RSSI. Dedup keys on actionID
where available, so a termination lands on the event it ends instead of
creating a second pin.
- denmEvents merges the MQTT and over-the-air sources and drops terminated
events. The V2X list view now shows hazards above the CAM stations; it
previously took no DENM parameter at all, so hazards reached the map but never
the list.
- DenmParser: the Use Case API sends causeCode as a string enum, so reading it
as an Int always yielded null.
Testing
- DenmAirReceiveTest covers the V2X_RX prefix and the decoder using real frames
from a live capture as fixtures. Expected values were cross-checked against
the ETSI ASN.1 modules via asn1tools, which agreed on all 1885 decodable
DENMs across the capture set, every field including detectionTime.
- Verified on hardware: a CiT One HLN-SV DENM decodes as cause 94/0 with a
1000 m relevance radius at 1 Hz alongside CAM, with no decode failures and no
unexpected BTP ports.
Also replaces em dashes with hyphens throughout the user-facing strings,
including the German translation.