2026-09-11 20:19:40 +02:00
|
|
|
# TODO
|
|
|
|
|
|
|
|
|
|
Engineering to-do list. The reviewer-facing open items live in
|
|
|
|
|
`docs/01-requirements-traceability.md` ("Open items"); this file is the working list behind them.
|
|
|
|
|
|
|
|
|
|
## Waiting on hardware
|
|
|
|
|
|
|
|
|
|
### Over-the-air check of the GN lifetime fix (added 2026-09-11)
|
|
|
|
|
|
|
|
|
|
`geonet.c` now writes GN lifetime `0x05` (1 s) instead of `0x83`, which decoded to 3200 s. Changed
|
|
|
|
|
in both `obu-firmware` and `obu-cam-transmistter`. Both still build (IDF 6.1 / 5.5.4), and the
|
2026-09-14 13:33:47 +02:00
|
|
|
compiled `geonet_wrap_shb` stores the new byte. Confirmed on air 2026-09-14. Nothing else
|
2026-09-11 20:19:40 +02:00
|
|
|
reads this byte (`gn_unwrap.c` ignores it, the app never sees GN headers), so the app does not
|
|
|
|
|
need updating alongside the firmware.
|
|
|
|
|
|
|
|
|
|
Needs: the phone with the app, the OBU ESP32-C5, and a **second** ESP32-C5 running
|
|
|
|
|
`its-g5-receiver-firmware` to capture with.
|
|
|
|
|
|
2026-09-14 13:33:47 +02:00
|
|
|
- [x] Flash `obu-firmware` (done 2026-09-14 on COM3; flash backed up first to
|
|
|
|
|
`Documents/micrOBU_workspace/firmware-backups/COM3-2026-09-14-before-secured-rx.bin`).
|
|
|
|
|
- [x] Capture with the receiver (COM8) into `its-g5-receiver-firmware/recordings/`.
|
|
|
|
|
- [x] `pcap_gn_tally.py` on capture_20260914_132126.pcap: our station sends SHB, port 2001,
|
|
|
|
|
lifetime `0x05`, same as both bench stations. It was `0x83` in the August captures.
|
|
|
|
|
- [x] Real-station CAMs/DENMs/SPATEM still reach the app (logcat: `handleCamUper`,
|
|
|
|
|
`handleDenmUper`, `handleSpatUper` all decoding, 2026-09-14).
|
|
|
|
|
- [x] Our own CAMs decode on air: 397 frames from station 999999 decode with asn1tools and
|
|
|
|
|
re-encode byte-identically.
|
|
|
|
|
- [ ] Confirm the CAM Pinger card's `tx fail` / oversize / CRC counters are 0 (needs a look at the
|
|
|
|
|
phone; not readable from the PC).
|
2026-09-11 20:19:40 +02:00
|
|
|
|
|
|
|
|
Partial check possible with one board and no phone: flash it, `idf.py -p COMx monitor`, and look
|
|
|
|
|
for `OCB @ 5900 MHz - TX/RX armed`. That proves the new build boots and brings the radio up, not
|
|
|
|
|
that it transmits correctly.
|
|
|
|
|
|
|
|
|
|
### obu-cam-transmistter yawRateConfidence fix (added 2026-09-11)
|
|
|
|
|
|
|
|
|
|
Its `cam.c` (compiled into that firmware) wrote `yawRateConfidence` as 3 bits / 7 instead of
|
|
|
|
|
4 bits / unavailable(8), the bug the app fixed on 2026-08-20. Fixed in it and in obu-firmware's
|
|
|
|
|
reference copy; asn1tools now decodes the CAM and re-encodes it byte-identically, and it builds on
|
2026-09-14 13:33:47 +02:00
|
|
|
IDF 5.5.4. Since 2026-09-14 the spare board on COM10 runs it as a bench beacon:
|
2026-09-11 20:19:40 +02:00
|
|
|
|
2026-09-14 13:33:47 +02:00
|
|
|
- [x] Done 2026-09-14: flashed on COM10 and captured on COM8. All 72 CAMs from station
|
|
|
|
|
195936478 (0x0BADC0DE) decode with asn1tools and re-encode byte-identically, so the
|
|
|
|
|
4-bit yawRateConfidence is right on air. COM10 now runs this beacon rather than
|
|
|
|
|
obu-firmware - reflash it if the spare is needed as an OBU again.
|
2026-09-11 20:19:40 +02:00
|
|
|
|
|
|
|
|
### Signed-message reception and exact payloads (added 2026-09-11)
|
|
|
|
|
|
|
|
|
|
obu-firmware's `gn_unwrap.c` now unwraps TS 103 097 signed packets (signature not verified,
|
|
|
|
|
reported as V2X_RX flags bit1) and cuts every message to the length its header declares, dropping
|
|
|
|
|
the 8 bytes the chip's RX appends to each frame, which were forwarded to the phone until now.
|
|
|
|
|
Verified on the host (`obu-firmware/test/host`: chain, replay of all recordings against asn1tools,
|
2026-09-14 13:33:47 +02:00
|
|
|
50M-iteration fuzz) and flashed to the production OBU on 2026-09-14. The remaining gap is signed
|
|
|
|
|
traffic to receive: real vehicles or
|
2026-09-11 20:19:40 +02:00
|
|
|
RSUs, since the bench CiT One sends unsigned. A second ESP32 running the receiver firmware is
|
|
|
|
|
optional, but shows what was on air at the time.
|
|
|
|
|
|
2026-09-14 13:33:47 +02:00
|
|
|
- [x] Flash obu-firmware (done 2026-09-14, COM3).
|
|
|
|
|
- [x] Unsigned bench traffic still decodes in the app, with messages now cut to their declared
|
|
|
|
|
length (CAM, DENM and SPATEM all decoding in logcat after the flash).
|
2026-09-11 20:19:40 +02:00
|
|
|
- [ ] Near signed traffic: signed CAMs/DENMs appear in the app, and a simultaneous capture shows
|
2026-09-14 13:33:47 +02:00
|
|
|
them on air (`pcap_gn_tally.py` lists them as `secured`). NOT possible at this bench: the
|
|
|
|
|
CiT One transmits unsigned (`ItsGnSecurity = 0`) and nothing else here signs. Needs a drive
|
|
|
|
|
past real RSUs, the CiT One switched to signed mode if its API allows, or a replay firmware
|
|
|
|
|
on a spare board that re-transmits the recorded signed frames.
|
|
|
|
|
- [ ] The heartbeat's oversize counter still counts over-long messages. Not exercised at the
|
|
|
|
|
bench: the SPATEMs here are ~340 bytes on air, far below the cap.
|
2026-09-11 20:19:40 +02:00
|
|
|
|
|
|
|
|
## Set up host testing
|
|
|
|
|
|
|
|
|
|
- [x] Install MSYS2 UCRT64 gcc (done 2026-09-11: gcc 16.2.0, GNU Make 4.4.1; chosen over WSL,
|
|
|
|
|
vanetza is not going to be built). Setup and the PATH gotcha: `obu-firmware/test/host/README.md`.
|
|
|
|
|
- [x] Host round-trip test `obu-firmware/test/host/test_chain.c` (`geonet_wrap_shb` ->
|
|
|
|
|
`dot11p_build_frame` -> `gn_unwrap_its`, byte-checked against the standard). Done
|
|
|
|
|
2026-09-11: 491 checks, 0 failed. Run `make` in that folder before flashing any firmware fix.
|
|
|
|
|
- [x] Replay of the recorded captures (`test_replay.c` + `check_replay.py`, independent asn1tools
|
|
|
|
|
check). Done 2026-09-11: C and Python agree on all 15 145 records.
|
|
|
|
|
- [x] Mutation fuzzer `fuzz_gn_unwrap.c`, inputs against a no-access guard page. Done 2026-09-11:
|
|
|
|
|
50 000 000 iterations, no crash. `make` runs a 2 000 000-iteration pass every time.
|
|
|
|
|
|
|
|
|
|
## Firmware ideas from the vanetza review (2026-09-11, not started)
|
|
|
|
|
|
|
|
|
|
Suggested order after the host tests exist:
|
|
|
|
|
|
|
|
|
|
- [x] **Read secured packets (GN NextHeader=2) without verifying them.** Done 2026-09-11 in
|
|
|
|
|
`gn_unwrap.c`, host-verified; flagged to the phone as V2X_RX flags bit1. On-air check under
|
|
|
|
|
"Waiting on hardware".
|
|
|
|
|
- [ ] **Forward the full GeoBroadcast area**: shape (circle/rectangle/ellipse), DistanceB, angle,
|
|
|
|
|
appended to the V2X_RX prefix behind a capability bit. Port vanetza's `geonet/areas.cpp`
|
|
|
|
|
`inside_or_at_border` to the app, which currently treats every area as a circle.
|
|
|
|
|
- [ ] **RX filtering before the serial link**: duplicate detection for GBC (last 8 sequence numbers
|
|
|
|
|
per source, as vanetza does), drop our own frames, reject GN version != 1.
|
|
|
|
|
- [ ] **Read the DCC-MCO field** (the 4 "reserved" bytes of an SHB header): neighbours' channel
|
|
|
|
|
busy ratio for free.
|
|
|
|
|
- [ ] **Minimum TX gap in firmware** as a DCC safety net (vanetza reactive table: 60 ms relaxed ...
|
|
|
|
|
460 ms restrictive), with a CBR estimate in the heartbeat.
|
|
|
|
|
- [ ] **Generic V2X_TX message** (BTP port, SHB/GBC, traffic class, lifetime, area) so the phone can
|
|
|
|
|
send DENM and VAM without reflashing. Consider QoS Data frames: vanetza's Cohda receive path
|
|
|
|
|
drops non-QoS ones.
|
|
|
|
|
|
|
|
|
|
Dropped: building vanetza as a GN/BTP oracle. Real captures (`pcap_gn_tally.py`), the host
|
|
|
|
|
round-trip test and `asn1tools` for UPER cover what it would have checked.
|
|
|
|
|
|
2026-09-14 13:33:47 +02:00
|
|
|
## Follow-ups found 2026-09-14
|
|
|
|
|
|
|
|
|
|
- [ ] **Commit the `live_capture.py` fix in the receiver repo.** Its console inserts a CR before
|
|
|
|
|
every LF, which also hits every 0x0a byte of the binary pcap stream, shifting pcap record
|
|
|
|
|
headers and frames. A 787 KB capture parsed cleanly for only 82 of ~2000 records, and DENMs
|
|
|
|
|
showed up on nonsense BTP ports. `undo_crlf()` now reverses it on the raw stream before
|
|
|
|
|
framing; afterwards a capture parsed to EOF and DENMs read as port 2002. This is the
|
|
|
|
|
"occasional byte inserted mid-frame" in the older recordings, so **every capture taken before
|
|
|
|
|
2026-09-14 is truncated at its first corrupted record** - re-measure anything derived from
|
|
|
|
|
them. The change is in the `its-g5-receiver-firmware` repo, uncommitted.
|
|
|
|
|
- [ ] **Do not open COM3's console while the phone is attached.** Opening it toggles DTR/RTS on the
|
|
|
|
|
CH343 and resets the OBU, which drops the phone's USB link and needs a manual Connect.
|
|
|
|
|
|
2026-09-11 20:19:40 +02:00
|
|
|
## Follow-ups found 2026-09-11
|
|
|
|
|
|
|
|
|
|
- [ ] **App: show the signed flag.** `V2xRxFrame.parse` in `SerialFrame.kt` only reads bit0 of
|
|
|
|
|
the flags byte; read bit1 (signed, not verified) and show it where messages are listed.
|
|
|
|
|
- [ ] **Messages that do not decode with asn1tools.** In the recordings, 56 from the CiT One
|
|
|
|
|
(`aa:f8:76:7d:bd:ad`: 54 CAMs of 245 bytes, 2 DENMs of 402 bytes) and one 218-byte CAM from
|
|
|
|
|
`6e:94:03:1b:05:26` fail against `cam_1_4_1`/`denm_1_3_1` + `cdd_1_3_1_1`, with or without the
|
|
|
|
|
old trailing bytes. A newer module version on the sender, or a sender bug; check what the
|
|
|
|
|
app's decoders make of them (`check_replay.py` lists the records).
|