Skip to content

feat(exi): AC-DER IEC/SAE support and repeated-particle array grammar fixes - #136

Open
mlitre wants to merge 1 commit into
mainfrom
fm/cbexigen-der-wpt-pr
Open

mlitre wants to merge 1 commit into
mainfrom
fm/cbexigen-der-wpt-pr

Conversation

@mlitre

@mlitre mlitre commented Sep 15, 2026

Copy link
Copy Markdown

Describe your changes

Builds on #127 by @milindur, squashed into one commit and co-authored to him. Adds AC-DER SAE, which #127 does not generate, and completes the array grammar for particles declared minOccurs >= 2:

  • The optional tail state's loop now targets itself rather than the next grammar. Before, an array whose repeated particle is followed by another particle silently truncated at minOccurs + 1 and returned success in both directions. ISO 15118-20 wireless power declares three such particles.
  • Encoders now emit the schema-maximum breakout that decoders have always read. Pre-existing and corpus wide: an array at exactly its declared maximum was written one bit wider than it was read, so a ten point DER curve, which is legal, did not round-trip. The breakout rule now lives in one place shared by both coders.

Issue ticket number and link

No existing ticket. Continues #127.

Verification

Every configured schema whose XSD is present regenerated, twice per arm with __pycache__ cleared between runs. The earlier round covered four ISO 15118-20 schemas only, not DIN 70121 or ISO 15118-2, because those XSDs were not in that checkout. It has since been redone with the full set: appHandshake, ISO 15118-2 and all five ISO 15118-20 variants, including WPT and both AC-DER schemas, which download from standards.iso.org alongside the base edition. DIN 70121 is still out of reach.

On the generator's own repeatability: it has been byte reproducible since bdf082f, cold and warm, so there is no run-to-run churn left to subtract here and every diff below is attributable.

Only encoders change from the breakout fix, and only by gaining it: 41 decoder breakouts had no encoder counterpart before, all 41 match on grammar id, threshold and targets after. The WPT decoder also changes, which is the point of the first fix: grammar 75 was a one bit state whose only exit was grammar_id = -1, so WPT_TxRxPackageSpecDataType was undecodable, and it is now the correct two mandatory states plus a tail offering the loop and the next particle. DER curve round-trips for n = 2..10 in both IEC and SAE.

The namespace element replacement guard, and why it went unseen

The verification above used to be scoped to four ISO 15118-20 schemas, excluding DIN 70121 and ISO 15118-2. That scope is exactly why this went unseen: the regression below lands entirely in ISO 15118-2, so no amount of care inside the verified set could have found it. It showed up the first time the same check was run with every downloadable schema present. Worth checking the scope of a verification before trusting its conclusion.

The guard in SchemaAnalyzer.__build_namespace_elements that skipped replacement for any type already carrying particles also caught ISO 15118-2's BodyType, which stopped being replaced and lost its union, emitting all 35 message bodies side by side:

sizeof(struct iso2_BodyType) sizeof(struct iso2_exiDocument)
with the guard 54,824 65,184
without it 13,824 24,184

EVerest's EvseV2G allocates two iso2_exiDocument per connection and clears both on every message, so that guard cost about 82 KB of extra zeroing per message on hardware that does not have it to spare.

The fix is deliberately narrow: the content_type/particles condition is removed and the substitution group head skip is kept. Measured with and without that one condition, over two cold runs of each arm, on this branch alone and on a merge with the element fragment grammar branch:

  • all twelve generated AC-DER IEC and SAE files are byte identical, so the condition was not load bearing for what it was added for;
  • the only files that move are three ISO 15118-2 ones, by 337 lines, which is the union coming back;
  • with it removed, seven probed ISO 15118-2 messages encode byte identically to what EVerest ships today.

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

@codacy-production

codacy-production Bot commented Sep 15, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 27 complexity · 0 duplication

Metric Results
Complexity 27
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@mlitre
mlitre force-pushed the fm/cbexigen-der-wpt-pr branch from 88aaf26 to 1e7f3c6 Compare September 15, 2026 13:31
Adds ISO 15118-20 Amd1 and AC-DER IEC schema support, wires up AC-DER
SAE alongside it, and corrects two defects in the array grammar the
generator emits for particles declared minOccurs >= 2.

A particle with minOccurs >= 2 needs mandatory states offering only a
START event, then an optional tail state offering both the loop and
whatever may follow it. That tail state's loop transition now targets
itself. It previously targeted the next sequential grammar, which is
harmless when the repeated particle is last in its type but caps the
array at minOccurs + 1 when other particles follow. ISO 15118-20
wireless power has three such particles (TxSpecData, RxSpecData and
PulseSequenceOrder, all minOccurs=2 maxOccurs=255), so the generated
WPT codec silently truncated those arrays while reporting success.

Encoders now also emit the loop breakout at the schema maximum that
every decoder already expected. Without it an encoder wrote a wider
END event code than the decoder read, so an array at exactly its
declared maximum did not round-trip. This was corpus wide rather than
specific to AC-DER: a ten point DER curve differed by one bit, as did
ISO 15118-20 TaxCosts. The rule deciding when a loop breaks out now
lives in one place shared by both coders, since the two must agree on
it to the bit.

Verified by regenerating every configured schema present, twice per
arm to rule out generator nondeterminism. Only encoders change, and
only by gaining the breakout: 41 decoder breakouts across four
schemas had no encoder counterpart before and match exactly after.
Round-trip probes cover n=2..10 for the DER curve in both IEC and
SAE, and a synthetic schema carrying both repeated particle shapes.

Co-authored-by: Christian Andersen <public@milindur.de>
Signed-off-by: Martin Litre <mnlitre@gmail.com>
@mlitre
mlitre force-pushed the fm/cbexigen-der-wpt-pr branch from 1e7f3c6 to 074de64 Compare September 16, 2026 14:56
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.

1 participant