Files
MicrOBU/microbu-esp32c5/README.md
T
Ashin Walpola 0e9525162d Keep the colleague's microbu-esp32c5 tree in this repository
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).
2026-09-23 17:46:40 +02:00

6.8 KiB

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