aas-submodel-validate
Template-conformance checking for AAS submodels — offline.
An Asset Administration Shell file can be perfectly valid against the AAS metamodel and still not be the submodel it claims to be: the wrong cardinalities, the wrong semantic identifiers, a mandatory VDI 2770 classification missing. This tool checks a submodel instance against its IDTA template — starting with IDTA 02004 Handover Documentation 2.0 — from the command line, on a machine with no internet connection, as a step in a build.
git clone https://github.com/dev365code/aas-submodel-validate && cd aas-submodel-validate
pip install .
smtv tests/corpus/idta/02004/example.aasx # IDTA's own published example
smtv your-submodel.aasx
The third line runs against the official example this repository vendors, so the first verdict needs nothing of your own. Replace it with your file for the fourth.
Or pip install aas-submodel-validate once the release has reached
PyPI; the CHANGELOG says which version is out.
For a machine with no package manager, build the single file once where there is a network and carry it:
python tools/build_zipapp.py # dist/smtv.pyz, about 220 KB
python dist/smtv.pyz your-submodel.aasx
Everything is inside it — this package and its one dependency — and nothing is compiled, so the same file runs on Linux, macOS and Windows, and it is an ordinary zip anyone who has to approve it can open and read. Two builds of one tree are byte-identical, so the hash on a release page is the hash of the file you carried in.
Reads .aasx (OPC containers, XML or JSON payload), AAS environment
.json/.xml, and bare Submodel .json. Exit codes: 0 nothing at error
severity, 1 at least one error, 2 could not run — which covers a path
that cannot be read and an input this reader refused, since nothing about
either was judged. Warnings and info do
not fail a build unless you ask with -W. -f json writes a versioned
machine-readable report, described in
docs/report-schema.md. One dependency
(aas-core3.0),
pure Python, no C extensions. Both wheels fit on a USB stick and
install with --no-index --find-links; the single file above needs not
even that.
What it checks
125 rules, 123 of them across three IDTA templates — 86 generated from the vendored official template files (cardinality, element kinds, value types, semantic identifiers at every nesting level), the rest hand-written where a template file cannot speak. The other two read the battery passport against Regulation (EU) 2023/1542 rather than against a template, over IDTA 02035-1, 02035-4 and 02035-5: one names a submodel identifier that two published templates claim, and one reports an element a template permits to be absent that a published legal reading requires — a file can be conformant to the template and not to the law, and those are different answers. It reports the one such disagreement that does not depend on the battery's category; eight more are known, counted in the report, and left unsaid because saying them without the category would tell one manufacturer to add what another's guidance forbids. X1, X2 and X4 are about the AASX/OPC package the submodel arrives in; X3 says a document would not parse, packaged or bare; and X5 is this reader's own bound on how much it will take in, whichever way it arrives. One, SMT-D1, asks whether the input brought a submodel this tool knows at all; and one, SMT-D2, says which template answered wherever two published templates share one submodel identifier and something had to choose.
| template | generated | hand-written |
|---|---|---|
| IDTA 02004 Handover Documentation 2.0.1 | 38 | the mandatory VDI 2770 classification and its twelve classes, English class names, the status vocabulary, dates that are dates, files that exist in the container, references that resolve |
| IDTA 02003 Technical Data 2.0.1 | 26 | dates that are dates, files that exist in the container, references that resolve |
| IDTA 02035-2 Digital Battery Passport part 2 1.0 | 22 | 02004's, minus the three whose elements this template drops |
02003 declares open content: §3.5 says the set of suitable semanticIds is not restricted, so its 36 placeholder elements generate no rules and a manufacturer's own properties pass without complaint. Near-miss identifiers are diagnosed rather than silently unmatched, in all three.
IDTA 02035-2 (Digital Battery Passport, part 2) publishes IDTA 02004's
submodel identifier and asks for less than it does, so which of the two
answers has to be chosen. Today that choice is the caller's:
--profile 02035-2 judges by the battery passport's table,
--profile 02004 by the Handover template's, and without the flag 02004
answers as it always has. Whenever a file declares the profile or the
flag is used, the report says which template answered and counts the
checks the two disagree about — what this run asked that the other would
not, or what it did not ask that the other would (SMT-D2). A plain
02004 file judged as 02004 draws nothing, because there was no choice
to report.
Beside the validator, data/battery-passport/ publishes machine-readable
indexes of what a battery passport is required to carry -- Annex XIII of
Regulation (EU) 2023/1542, the Commission's data-point guidance, the
Battery Pass long list, and the IDTA 02035/02099 templates -- with a
join across all four whose coverage is stated as a floor. The sources
are pinned by hash, not mirrored; data/battery-passport/README.md says
how to rebuild every index from them.
The AAS metamodel itself is relayed from aas-core3.0's verification in
a separate meta channel — warnings by default, --strict-meta to
promote — and never re-implemented here.
error SMT-D1 no submodel declares a semanticId this tool has a template table for
saw semanticId value(s): urn:somecompany:docs
fix: If the submodel means one of the templates this tool has a table for, give it that template's semanticId: 0173-1#01-AHF578#003 for Handover Documentation (IDTA 02004); 0173-1#01-AHX837#002 for Technical Data (IDTA 02003). If it means a template this tool has no table for, leave the identifier alone -- it is doing its job, and this finding only says nothing here judged the submodel against a template.
1 error(s), 0 warning(s), 0 info — machine-docs.json · judged 0 of 1 submodel
The sample above is generated by a test and fails the build when it goes stale; the rule counts (125, 86) are pinned the same way.
Where this sits
aas-test-engines is the official conformance tooling for the AAS metamodel, serialisation, AASX packaging and APIs; as of v1.0.3 its submodel-template layer covers two templates (Contact Information, Digital Nameplate). This project is the complementary layer for the templates it supports, starting with IDTA 02004: does a given submodel instance conform to the template — cardinality, semantic identifiers, the VDI 2770 classification rules — with a remedy sentence for every finding, offline. Metamodel checking is deliberately delegated to aas-core3.0's verification and reported in a separate channel, never re-invented here.
What it refuses to do is written down in docs/scope.md; every chosen reading of the template, with evidence, in docs/divergences.md; the shape of the JSON report, and what its version number promises, in docs/report-schema.md. Where to send a question, and what makes a report answerable, in SUPPORT.md.
Licence
Apache-2.0, © 2026 Wooyong Lee. Contributions need a Signed-off-by
line (DCO); see CONTRIBUTING.md.
This is an unofficial project, not affiliated with or endorsed by IDTA or the Eclipse BaSyx project. "AAS", "Asset Administration Shell" and template identifiers are used descriptively.
Release files for aas-submodel-validate 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aas_submodel_validate-0.1.0.tar.gz | 1.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aas_submodel_validate-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.7 MB
Release files / aas_submodel_validate-0.1.0.tar.gz
| Download URL | aas_submodel_validate-0.1.0.tar.gz |
|---|---|
| Size | 1.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f335b034dcf4b7422f24b25c3c84c801e88d0b28c6046fa08bd0e4a5da33cf0d
|
|
BLAKE2b-256 checksum How to use checksums |
b6395580b5dafec6833563f005757e2e6c97635128acb1447084382c74f5c8a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / aas_submodel_validate-0.1.0-py3-none-any.whl
| Download URL | aas_submodel_validate-0.1.0-py3-none-any.whl |
|---|---|
| Size | 114.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
57eff6f6acb642547cf4f5243a24c8343b656ef4b72c86c3664781a20a31dfda
|
|
BLAKE2b-256 checksum How to use checksums |
6da4da7c730cfbbf9040992b915c42cdd49db3090bccd833f4ee4d457e2d2cb1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency log