Files
MicrOBU/asn1/README.md
T
Ashin Walpola b2b57fa39e Vendor the ASN.1 modules the codecs are verified against; untrack IDE churn
asn1/
Three tests assert exact bytes - CamEncodeGoldenTest, DenmAirReceiveTest and
SpatemUperCodecTest - and their expected values came from asn1tools compiled
against ETSI modules that existed only as an untracked working copy on one
machine. A golden-byte fixture nobody else can regenerate is a fixture nobody
can safely touch, so the modules are now in the repo.

Only the seven .asn files those tests need are copied, 576 KB of a 4.2 MB
checkout; the upstream Rust parser is not used by this project at all. Verified
sufficient in isolation: copied into an empty directory, all three specs compile
and reproduce the committed golden CAM bytes byte-identically.

Source is consider it GmbH's C-ITS-Parser (github.com/consider-it/C-ITS-Parser)
at f457426, MIT licensed - LICENSE is retained alongside as that requires. The
schemas themselves are ETSI's standard definitions; upstream's contribution is
assembling them into a compilable set. asn1/README.md records the provenance,
which module pairs with which message, and the rule that matters: never
regenerate a golden fixture from this project's own encoder, because sharing a
mistake between encoder and decoder is exactly the failure these files exist to
catch.

Doc references in the codecs and tests now point at asn1/ instead of the
untracked checkout, and C-ITS-Parser/ is gitignored so the working copy beside
the project is never picked up.

Untracked local state
- .idea/deploymentTargetSelector.xml rewrites itself on every deploy, so it has
  been showing as modified in essentially every commit. Along with
  deviceManager.xml, appInsightsSettings.xml and studiobot.xml it is per-machine
  state, not project configuration.
- obu-firmware/sdkconfig.old is ESP-IDF build output - it is the previous
  sdkconfig, rewritten on every build. sdkconfig.defaults remains tracked, since
  that is the configuration actually chosen.

All five stay on disk; only the tracking is removed. Also ignores
.claude/settings.local.json, which is per-machine, while leaving the skills
beside it committable as project knowledge.
2026-08-21 14:28:57 +02:00

3.2 KiB

ETSI ASN.1 modules

The ASN.1 schemas this project's UPER codecs are validated against. Schemas only — no parser code. Nothing in the app or the firmware reads these files at build or run time; they exist so the hand-written codecs in app/src/main/java/.../domain/asn1/ can be checked against an independent implementation.

Why this is here rather than just documented

Three of this project's tests assert exact bytes:

  • CamEncodeGoldenTest — the CAM this app transmits, byte for byte
  • DenmAirReceiveTest, SpatemUperCodecTest — real captured frames with field values

Those expected values were produced by decoding with asn1tools compiled from these modules. Without them the fixtures cannot be regenerated or re-verified, and a golden-byte test you cannot regenerate is a test nobody can safely touch.

This matters because the project has shipped the same class of bug three times: a field encoded with the wrong number of bits, which this codebase then read back with the same wrong number. Phone and ESP32 agree perfectly with each other and with nothing else, so every internal round-trip test passes while the frames on air are malformed (CurvatureCalculationMode, the GeoNetworking reserved bytes, yawRateConfidence). Only a second, independent implementation catches that — which is what these modules provide.

Provenance

Taken from consider it GmbH's C-ITS-Parser:

Only the seven .asn files below are copied, out of a 4.2 MB checkout. The upstream Rust parser is not used by this project in any way. The schemas themselves are ETSI's standard definitions; the upstream repo's contribution is assembling them into a compilable set.

file used for
cam_1_4_1.asn + cdd_1_3_1_1.asn CAM encode/decode
denm_1_3_1.asn + cdd_1_3_1_1.asn DENM decode
spatem_2_2_1.asn, mapem_2_2_1.asn, dsrc_2_2_1.asn, cdd_2_2_1.asn SPATEM/MAPEM decode

Note CAM/DENM use the release-1 common dictionary (cdd_1_3_1_1) while SPATEM/MAPEM use release 2 (cdd_2_2_1). Both are needed; they are not interchangeable.

These seven were verified sufficient on their own: copied into an empty directory, all three specs compile and reproduce the committed golden bytes.

Regenerating a fixture

Requires Python with asn1tools (verified with 0.167.0):

import asn1tools
spec = asn1tools.compile_files(["asn1/cam_1_4_1.asn", "asn1/cdd_1_3_1_1.asn"], "uper")
spec.decode("CAM", raw_uper_bytes)

For SPATEM, compile spatem_2_2_1.asn, mapem_2_2_1.asn, dsrc_2_2_1.asn, cdd_2_2_1.asn together and decode "SPATEM".

Never regenerate a golden fixture from this project's own encoder output — that is precisely the mistake these files exist to catch. Regenerate through asn1tools, or the test is worthless.

Updating

Re-pin deliberately, not casually. If a newer ETSI release is adopted, copy the new modules, then re-run the golden-byte tests and confirm any change in expected bytes is explained by the spec change rather than by a decoder regression.