Skip to content

feat: add Canonical EXI encoding support for ISO 15118-2/-20 Plug & Charge#126

Open
jayharper wants to merge 4 commits intoEVerest:mainfrom
jayharper:feature/canonical-exi-plug-and-charge
Open

feat: add Canonical EXI encoding support for ISO 15118-2/-20 Plug & Charge#126
jayharper wants to merge 4 commits intoEVerest:mainfrom
jayharper:feature/canonical-exi-plug-and-charge

Conversation

@jayharper
Copy link
Copy Markdown

Describe your changes

Adds opt-in Canonical EXI code generation for ISO 15118-2 and ISO 15118-20 Plug & Charge XML signature workflows (digest computation over EXI-encoded signed fragments).

When canonical_exi_enabled = 1 is set in config.py, the generator produces a 2-mode runtime system controlled by a canonical_mode field on exi_bitstream_t:

  • mode=0 (EXI_MODE_STANDARD): schema-informed standard EXI — existing behavior, unchanged
  • mode=1 (EXI_MODE_CANONICAL): Canonical EXI for Plug & Charge — 0x80 header, bit-packed, type-aware encoding per W3C Canonical EXI specification

The feature is disabled by default (canonical_exi_enabled = 0), so existing users are unaffected.

What changed

Generator (Python):

  • canonical_exi_enabled config flag threaded through FileGenerator, tools_config, and Jinja template rendering
  • W3C-compliant canonical attribute ordering in SchemaAnalyzer (xsi:type first, xsi:nil second, then lexicographic by local_name + namespace_uri)
  • namespace_uri field added to Particle dataclass for attribute sort key
  • Recursive schema import processing for complete fragment grammar discovery (previously only 1 level deep)

Templates (Jinja → generated C):

  • exi_bitstream_t gains canonical_mode field and EXI_MODE_STANDARD/EXI_MODE_CANONICAL constants
  • exi_basetypes_encoder adds exi_basetypes_encoder_string_len() for string table partition prefix encoding
  • exi_types_decoder adds decode_exi_type_base64_binary() for base64Binary decoding
  • DecodeTypeBase64BinarySimple.jinja fix for correct nesting depth
  • New error codes (EXI_ERROR__INVALID_LEXICAL_VALUE, EXI_ERROR__NUMERIC_OVERFLOW) for canonical decoding validation
  • exi_types_encoder.h added to all encoder include lists

Validation

  • Byte-identical output against EXIficient reference implementation for all 8 ISO 15118-20 signed fragment types
  • SHA-512 digest match and end-to-end signature verification (RSA-SHA512 + ECDSA-SHA256)
  • Validated against Keysight SL1550A EVCC live hardware (byte-identical 2,247-byte canonical output)

Issue ticket number and link

Closes #116

Checklist before requesting a review

  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • I read the contribution documentation and made sure that my changes meet its requirements

…harge

Add opt-in Canonical EXI code generation (canonical_exi_enabled config flag)
for ISO 15118-2 and ISO 15118-20 Plug & Charge XML signature workflows.

When enabled, the generator produces a 2-mode runtime system:
- mode=0 (EXI_MODE_STANDARD): schema-informed standard EXI (0x80 header, bit-packed)
- mode=1 (EXI_MODE_CANONICAL): Canonical EXI for Plug & Charge (0x80 header,
  bit-packed, type-aware encoding per W3C Canonical EXI specification)

Key changes:
- Runtime canonical_mode field in exi_bitstream_t struct, set by caller
- W3C-compliant canonical attribute ordering (xsi:type, xsi:nil, then
  lexicographic by local_name + namespace_uri)
- Recursive schema import processing for complete fragment grammar discovery
- String table partition prefix encoding for canonical string values
- base64Binary decoder fix for correct nesting depth
- New error codes for canonical decoding validation
- exi_types_encoder.h included in all encoder configurations

The feature is disabled by default (canonical_exi_enabled = 0). Set to 1
in config.py to generate canonical EXI code paths.

Validated against EXIficient reference implementation (8/8 fragment digest
match, RSA-SHA512 + ECDSA-SHA256 signature verification) and Keysight
SL1550A EVCC live hardware (byte-identical 2,247-byte canonical output).

Signed-off-by: jharper <jharper@anl.gov>
@jayharper jayharper force-pushed the feature/canonical-exi-plug-and-charge branch from 07c6f08 to a1c87d4 Compare March 18, 2026 16:25
@kwoyhope
Copy link
Copy Markdown

kwoyhope commented Mar 24, 2026

Hello @jayharper ,
It seems that there're missing "exi_types_encoder.c.jinja, exi_types_encoder.h.jinja" files.
And how(where) can it be used exi_bitstream.canonical_mode?

Add exi_types_encoder.c.jinja and exi_types_encoder.h.jinja templates
for generating the EXI type encoder (hexBinary, base64Binary). Register
the new templates in config.py so the generator produces
exi_types_encoder.c and exi_types_encoder.h alongside the existing
exi_types_decoder files.

Signed-off-by: jharper <jharper@anl.gov>
@jayharper
Copy link
Copy Markdown
Author

@kwoyhope Good catch — the exi_types_encoder.c.jinja and exi_types_encoder.h.jinja templates were missing. I've added them in the latest commit along with the exi_types_encoder config entry so the generator produces those files.

Regarding canonical_mode usage — the caller sets it on the exi_bitstream_t before encoding:

exi_bitstream_t stream;
exi_bitstream_init(&stream, buffer, buffer_size, 0, NULL);
stream.canonical_mode = EXI_MODE_CANONICAL;  // 1 = Canonical EXI for Plug & Charge
// ... then call the encode functions as normal

The two modes:

  • EXI_MODE_STANDARD (0): default, existing behavior unchanged
  • EXI_MODE_CANONICAL (1): Canonical EXI for ISO 15118-2/-20 Plug & Charge — same 0x80 header and bit-packed alignment, but with type-aware encoding paths (e.g. exi_basetypes_encoder_string_len() for string table partition prefixes)

The generated encoder code and exi_types_encoder.c functions use these modes internally where encoding differs between standard and canonical EXI.

@codacy-production
Copy link
Copy Markdown

codacy-production bot commented Mar 31, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 8 complexity . 0 duplication

Metric Results
Complexity 8
Duplication 0

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

Signed-off-by: jharper <jharper@anl.gov>
Fixes Codacy "statement has no effect" warning in tools_config.py.

Signed-off-by: jharper <jharper@anl.gov>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ISO15118-20 Canonical EXI support

3 participants