obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
micrOBU ESP32-C5
A standalone ITS-G5 (802.11p) VRU (Vulnerable Road User) ITS-S station on the
ESP32-C5: firmware, the embedded Vanetza
C-ITS protocol stack (external/vanetza-idf/, see
PROVENANCE.md), a phone-emulator
example for the station-internal link, a localhost PKI reference chain, a
Wireshark VAM dissector and the V2X2MAP
receiver bridge.
A fresh clone can send a real, signed VAM (VRU Awareness Message) over the
air in a handful of commands — see Send a signed VAM
below. station-link/python/demo-chain.vcr is a disposable, non-EU-registered
test credential chain generated specifically for this purpose (see
Security note on credentials); it carries no
real-world trust and is safe to ship.
Quickstart
1. Build & flash the ESP32-C5 firmware
Requires ESP-IDF 6.0.2 with the esp32c5 target.
cd firmware
idf.py set-target esp32c5
idf.py build
idf.py -p COM<PORT> flash monitor
2. Install the Wireshark VAM dissector
Wireshark decodes IEEE 1609.2 / ETSI TS 103 097 secured packets only down to
unsecuredData unless the PSID is registered in its dissector table. PSID
638 (VRU Awareness Service, ETSI TS 102 965) is not registered by default
in Wireshark 4.x, so signed VAM traffic stops decoding at the security
envelope without this plugin.
# Windows
Copy-Item tools\wireshark\psid-vru.lua "$env:APPDATA\Wireshark\plugins\"
# Linux
mkdir -p ~/.local/lib/wireshark/plugins && cp tools/wireshark/psid-vru.lua ~/.local/lib/wireshark/plugins/
# macOS
mkdir -p ~/.config/wireshark/plugins && cp tools/wireshark/psid-vru.lua ~/.config/wireshark/plugins/
Verify under Help → About Wireshark → Plugins, or use it directly with tshark:
tshark -X lua_script:tools/wireshark/psid-vru.lua -r capture.pcap
See tools/wireshark/README.md for details.
3. Install Python dependencies
pip install -r station-link/python/requirements.txt
pip install -r tools/v2x2map-0.3.0/bridge/requirements.txt
4. Send a signed VAM in a few commands
With the firmware flashed (step 1) and the ESP32-C5 connected over USB Serial/JTAG, the phone emulator provisions the disposable demo credential chain and starts a small VRU basic service that assembles and transmits VAMs:
python station-link/python/phone_emulator.py \
--port COM<PORT> --bundle station-link/python/demo-chain.vcr \
--radio txrx --duration 30
That's it — the micrOBU signs every VAM with the demo AT ticket (VRU ITS-AID
638, psid 638 ssp 01) and transmits it over ITS-G5. Capture it with a
second ITS-G5-capable radio (or the V2X2MAP bridge
below) and decode it with the Wireshark dissector
from step 2.
To provision over BLE instead of USB, or to mirror packets to a .pcap
without radiating, see the header of
phone_emulator.py for the
--ble, --radio off --divert --pcap and full --pki-* (real online TS
102 941 enrolment/authorization) variants, and
station-link/README.md for the link protocol
itself.
5. Run the V2X2MAP receiver bridge (optional)
A second ESP32-C5 flashed with the receiver firmware in
tools/v2x2map-0.3.0/bridge/firmware/
can feed a live web dashboard:
python tools/v2x2map-0.3.0/bridge/its_g5_bridge.py --port COM<PORT> --dashboard-port 8080 --open-browser
Open http://localhost:8080 if it doesn't open automatically. This tool
decodes VAMs for display but does not verify signatures (see
tools/v2x2map-0.3.0/README.md).
Repository layout
| Path | Contents |
|---|---|
firmware/ |
ESP-IDF firmware project for the ESP32-C5 VRU ITS-S |
external/vanetza-idf/ |
Vanetza C-ITS stack + ESP-IDF port (upstream provenance in PROVENANCE.md) |
station-link/ |
Station-internal link protocol, Python client library, phone emulator |
pki/ |
Localhost PKI reference chain (root/AA/AT tooling); see security note |
tools/wireshark/ |
PSID 638 (VRU) Wireshark Lua dissector |
tools/v2x2map-0.3.0/ |
Vendored V2X2MAP receiver bridge and live dashboard |
Security note on credentials
pki/uml-l0-rca/ documents the tooling for a real, EU CCMS L0 ECTL-registered
root CA used elsewhere in the wider micrOBU project. Its private key material
is intentionally not in this repository — .gitignore also backstops
this (*.vkey, *.ekey, private/).
station-link/python/demo-chain.vcr is unrelated: a separate, throwaway,
non-registered root/AA/AT chain generated specifically for this repo's
quickstart with pki/uml-l0-rca/bin/windows/vidf_issue.exe. Its
HashedId8 values do not match the registered root, it grants no real-world
trust, and regenerating it is safe:
$pool = "<some scratch directory>"
$exe = "pki\uml-l0-rca\bin\windows\vidf_issue.exe"
openssl ecparam -name prime256v1 -genkey -noout -out "$pool\demo_root_key.pem"
& $exe root --key "$pool\demo_root_key.pem" --name "Demo Root (NOT REGISTERED)" --id DEMO_RCA --out $pool --years 10
& $exe authority --issuer "$pool\DEMO_RCA.oer" --issuer-key "$pool\demo_root_key.pem" --name "Demo AA" --id DEMO_AA --out $pool --years 5
& $exe ticket --issuer "$pool\DEMO_AA.oer" --issuer-key "$pool\DEMO_AA.vkey" --id DEMO_AT --out $pool --hours 8760 --root "$pool\DEMO_RCA.oer"
python external\vanetza-idf\ports\esp_idf\tools\credential_bundle.py build `
--pool $pool --root DEMO_RCA --aa DEMO_AA --at DEMO_AT --out station-link\python\demo-chain.vcr
pki/uml-l0-rca/reference-generator/ cross-validates certificate generation
against an independent Rust implementation (TheEnbyperor/c-its,
pinned commit in reference-generator/README.md).
Its vendored crates (vendor/) are excluded from this repository by
.gitignore for size; regenerate with cargo vendor from that directory's
Cargo.lock, or use vidf_issue directly as shown above — the vendor tree
is only needed for that independent cross-check, not for ordinary use.
License / provenance
- Vanetza and its ESP-IDF port: BSD-3-Clause, see external/vanetza-idf/LICENSE.md and external/vanetza-idf/PROVENANCE.md.
- V2X2MAP bridge: MIT, see tools/v2x2map-0.3.0/LICENSE.