Skip to content

Commit 2063c8a

Browse files
authored
Merge pull request #174 from eclipse-basyx/improve/V30
Implement v3.0 of the metamodel specification For the detailed documentation of the changes, please refer to the [prior PRs](https://github.com/eclipse-basyx/basyx-python-sdk/pulls?page=4&q=is%3Apr+base%3Aimprove%2FV30)
2 parents 662ccf6 + 2db802b commit 2063c8a

File tree

121 files changed

+29485
-13997
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+29485
-13997
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# Coverage artifacts
1919
/.coverage
2020
/htmlcov/
21+
/docs/build/
2122

2223
# customized config files
2324
/test/test_config.ini

README.md

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22

33
(formerly known as PyI40AAS – Python Industry 4.0 Asset Administration Shell)
44

5-
The Eclipse BaSyx Python project focuses on providing a Python implementation of the Asset Administration Shell (AAS) for Industry 4.0 Systems,
6-
compliant with the meta model and interface specification provided in
7-
[the document “Details of the Asset Administration Shell” (v2.0.1)](https://www.plattform-i40.de/IP/Redaktion/DE/Downloads/Publikation/Details_of_the_Asset_Administration_Shell_Part1_V2.html).
8-
It currently adheres to version 2.0.1 of the specification.
9-
An updated version with support for version 3.0RC01 is already in preparation and will be made available on an additional branch of this repository and in a future major release.
5+
The Eclipse BaSyx Python project focuses on providing a Python implementation of the Asset Administration Shell (AAS)
6+
for Industry 4.0 Systems.
7+
These are the currently implemented specifications:
8+
9+
| Specification | Version |
10+
|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
11+
| Part 1: Metamodel | [v3.0 (01001-3-0)](https://industrialdigitaltwin.org/content-hub/aasspecifications/idta_01001-3-0_metamodel) |
12+
| Part 2: API | not implemented yet |
13+
| Part 3a: Data Specification IEC 61360 | [v3.0 (01003-a-3-0)](https://industrialdigitaltwin.org/content-hub/aasspecifications/idta_01003-a-3-0_data_specification) |
14+
| Part 5: Package File Format (AASX) | [v3.0 (01005-3-0)](https://industrialdigitaltwin.org/content-hub/aasspecifications/idta-01005-3-0_package_file_format_aasx) |
1015

1116
## Features
1217

13-
* Modelling of AASs as Python objects (according to DotAAS sec. 4)
14-
* **except for**: Security extension of the metamodel (according to DotAAS sec. 5), *HasDataSpecification*
15-
* Reading and writing of AASX package files (according to DotAAS sec. 6)
16-
* (De-)serialization of AAS objects into/from JSON and XML (according to DotAAS sec. 7)
18+
* Modelling of AASs as Python objects
19+
* **except for**: *HasDataSpecification*
20+
* Reading and writing of AASX package files
21+
* (De-)serialization of AAS objects into/from JSON and XML
1722
* Storing of AAS objects in CouchDB, Backend infrastructure for easy expansion
1823
* Compliance checking of AAS XML and JSON files
1924

@@ -53,9 +58,12 @@ Optional production usage dependencies:
5358
* For using the Compliance Tool to validate JSON files against the JSON Schema: `jsonschema` and its
5459
dependencies (MIT License, Apache License, PSF License)
5560

56-
Development/testing/example dependencies (see `requirements.txt`):
61+
Development/testing/documentation/example dependencies (see `requirements.txt`):
5762
* `jsonschema` and its dependencies (MIT License, Apache License, PSF License)
5863
* `psutil` (BSD 3-clause License)
64+
* `Sphinx` and its dependencies (multiple licenses)
65+
* `sphinx-rtd-theme` and its dependencies
66+
* `sphinx-argparse` (MIT License)
5967

6068
Dependencies for building the documentation:
6169
* `Sphinx` and its dependencies (BSD 2-clause License, MIT License, Apache License)
@@ -89,19 +97,17 @@ Create a `Submodel`:
8997
```python
9098
from basyx.aas import model # Import all BaSyx Python SDK classes from the model package
9199

92-
identifier = model.Identifier('https://acplt.org/Simple_Submodel', model.IdentifierType.IRI)
93-
submodel = model.Submodel(identification=identifier)
100+
identifier = 'https://acplt.org/Simple_Submodel'
101+
submodel = model.Submodel(identifier)
94102
```
95103

96104
Create a `Property` and add it to the `Submodel`:
97105
```python
98-
# create a global reference to a semantic description of the property
99-
semantic_reference = model.Reference(
106+
# create an external reference to a semantic description of the property
107+
semantic_reference = model.ExternalReference(
100108
(model.Key(
101-
type_=model.KeyElements.GLOBAL_REFERENCE,
102-
local=False,
103-
value='http://acplt.org/Properties/SimpleProperty',
104-
id_type=model.KeyType.IRI
109+
type_=model.KeyTypes.GLOBAL_REFERENCE,
110+
value='http://acplt.org/Properties/SimpleProperty'
105111
),)
106112
)
107113
property = model.Property(

basyx/aas/adapter/_generic.py

Lines changed: 82 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12,87 +12,104 @@
1212

1313
from basyx.aas import model
1414

15-
MODELING_KIND: Dict[model.ModelingKind, str] = {
16-
model.ModelingKind.TEMPLATE: 'Template',
17-
model.ModelingKind.INSTANCE: 'Instance'}
15+
# XML Namespace definition
16+
XML_NS_MAP = {"aas": "https://admin-shell.io/aas/3/0"}
17+
XML_NS_AAS = "{" + XML_NS_MAP["aas"] + "}"
18+
19+
MODELLING_KIND: Dict[model.ModellingKind, str] = {
20+
model.ModellingKind.TEMPLATE: 'Template',
21+
model.ModellingKind.INSTANCE: 'Instance'}
1822

1923
ASSET_KIND: Dict[model.AssetKind, str] = {
2024
model.AssetKind.TYPE: 'Type',
21-
model.AssetKind.INSTANCE: 'Instance'}
25+
model.AssetKind.INSTANCE: 'Instance',
26+
model.AssetKind.NOT_APPLICABLE: 'NotApplicable'}
27+
28+
QUALIFIER_KIND: Dict[model.QualifierKind, str] = {
29+
model.QualifierKind.CONCEPT_QUALIFIER: 'ConceptQualifier',
30+
model.QualifierKind.TEMPLATE_QUALIFIER: 'TemplateQualifier',
31+
model.QualifierKind.VALUE_QUALIFIER: 'ValueQualifier'}
32+
33+
DIRECTION: Dict[model.Direction, str] = {
34+
model.Direction.INPUT: 'input',
35+
model.Direction.OUTPUT: 'output'}
2236

23-
KEY_ELEMENTS: Dict[model.KeyElements, str] = {
24-
model.KeyElements.ASSET: 'Asset',
25-
model.KeyElements.ASSET_ADMINISTRATION_SHELL: 'AssetAdministrationShell',
26-
model.KeyElements.CONCEPT_DESCRIPTION: 'ConceptDescription',
27-
model.KeyElements.SUBMODEL: 'Submodel',
28-
model.KeyElements.ANNOTATED_RELATIONSHIP_ELEMENT: 'AnnotatedRelationshipElement',
29-
model.KeyElements.BASIC_EVENT: 'BasicEvent',
30-
model.KeyElements.BLOB: 'Blob',
31-
model.KeyElements.CAPABILITY: 'Capability',
32-
model.KeyElements.CONCEPT_DICTIONARY: 'ConceptDictionary',
33-
model.KeyElements.DATA_ELEMENT: 'DataElement',
34-
model.KeyElements.ENTITY: 'Entity',
35-
model.KeyElements.EVENT: 'Event',
36-
model.KeyElements.FILE: 'File',
37-
model.KeyElements.MULTI_LANGUAGE_PROPERTY: 'MultiLanguageProperty',
38-
model.KeyElements.OPERATION: 'Operation',
39-
model.KeyElements.PROPERTY: 'Property',
40-
model.KeyElements.RANGE: 'Range',
41-
model.KeyElements.REFERENCE_ELEMENT: 'ReferenceElement',
42-
model.KeyElements.RELATIONSHIP_ELEMENT: 'RelationshipElement',
43-
model.KeyElements.SUBMODEL_ELEMENT: 'SubmodelElement',
44-
model.KeyElements.SUBMODEL_ELEMENT_COLLECTION: 'SubmodelElementCollection',
45-
model.KeyElements.VIEW: 'View',
46-
model.KeyElements.GLOBAL_REFERENCE: 'GlobalReference',
47-
model.KeyElements.FRAGMENT_REFERENCE: 'FragmentReference'}
37+
STATE_OF_EVENT: Dict[model.StateOfEvent, str] = {
38+
model.StateOfEvent.ON: 'on',
39+
model.StateOfEvent.OFF: 'off'}
4840

49-
KEY_TYPES: Dict[model.KeyType, str] = {
50-
model.KeyType.CUSTOM: 'Custom',
51-
model.KeyType.IRDI: 'IRDI',
52-
model.KeyType.IRI: 'IRI',
53-
model.KeyType.IDSHORT: 'IdShort',
54-
model.KeyType.FRAGMENT_ID: 'FragmentId'}
41+
REFERENCE_TYPES: Dict[Type[model.Reference], str] = {
42+
model.ExternalReference: 'ExternalReference',
43+
model.ModelReference: 'ModelReference'}
5544

56-
IDENTIFIER_TYPES: Dict[model.IdentifierType, str] = {
57-
model.IdentifierType.CUSTOM: 'Custom',
58-
model.IdentifierType.IRDI: 'IRDI',
59-
model.IdentifierType.IRI: 'IRI'}
45+
KEY_TYPES: Dict[model.KeyTypes, str] = {
46+
model.KeyTypes.ASSET_ADMINISTRATION_SHELL: 'AssetAdministrationShell',
47+
model.KeyTypes.CONCEPT_DESCRIPTION: 'ConceptDescription',
48+
model.KeyTypes.SUBMODEL: 'Submodel',
49+
model.KeyTypes.ANNOTATED_RELATIONSHIP_ELEMENT: 'AnnotatedRelationshipElement',
50+
model.KeyTypes.BASIC_EVENT_ELEMENT: 'BasicEventElement',
51+
model.KeyTypes.BLOB: 'Blob',
52+
model.KeyTypes.CAPABILITY: 'Capability',
53+
model.KeyTypes.DATA_ELEMENT: 'DataElement',
54+
model.KeyTypes.ENTITY: 'Entity',
55+
model.KeyTypes.EVENT_ELEMENT: 'EventElement',
56+
model.KeyTypes.FILE: 'File',
57+
model.KeyTypes.MULTI_LANGUAGE_PROPERTY: 'MultiLanguageProperty',
58+
model.KeyTypes.OPERATION: 'Operation',
59+
model.KeyTypes.PROPERTY: 'Property',
60+
model.KeyTypes.RANGE: 'Range',
61+
model.KeyTypes.REFERENCE_ELEMENT: 'ReferenceElement',
62+
model.KeyTypes.RELATIONSHIP_ELEMENT: 'RelationshipElement',
63+
model.KeyTypes.SUBMODEL_ELEMENT: 'SubmodelElement',
64+
model.KeyTypes.SUBMODEL_ELEMENT_COLLECTION: 'SubmodelElementCollection',
65+
model.KeyTypes.SUBMODEL_ELEMENT_LIST: 'SubmodelElementList',
66+
model.KeyTypes.GLOBAL_REFERENCE: 'GlobalReference',
67+
model.KeyTypes.FRAGMENT_REFERENCE: 'FragmentReference'}
6068

6169
ENTITY_TYPES: Dict[model.EntityType, str] = {
6270
model.EntityType.CO_MANAGED_ENTITY: 'CoManagedEntity',
6371
model.EntityType.SELF_MANAGED_ENTITY: 'SelfManagedEntity'}
6472

65-
IEC61360_DATA_TYPES: Dict[model.concept.IEC61360DataType, str] = {
66-
model.concept.IEC61360DataType.DATE: 'DATE',
67-
model.concept.IEC61360DataType.STRING: 'STRING',
68-
model.concept.IEC61360DataType.STRING_TRANSLATABLE: 'STRING_TRANSLATABLE',
69-
model.concept.IEC61360DataType.REAL_MEASURE: 'REAL_MEASURE',
70-
model.concept.IEC61360DataType.REAL_COUNT: 'REAL_COUNT',
71-
model.concept.IEC61360DataType.REAL_CURRENCY: 'REAL_CURRENCY',
72-
model.concept.IEC61360DataType.BOOLEAN: 'BOOLEAN',
73-
model.concept.IEC61360DataType.URL: 'URL',
74-
model.concept.IEC61360DataType.RATIONAL: 'RATIONAL',
75-
model.concept.IEC61360DataType.RATIONAL_MEASURE: 'RATIONAL_MEASURE',
76-
model.concept.IEC61360DataType.TIME: 'TIME',
77-
model.concept.IEC61360DataType.TIMESTAMP: 'TIMESTAMP',
73+
IEC61360_DATA_TYPES: Dict[model.base.DataTypeIEC61360, str] = {
74+
model.base.DataTypeIEC61360.DATE: 'DATE',
75+
model.base.DataTypeIEC61360.STRING: 'STRING',
76+
model.base.DataTypeIEC61360.STRING_TRANSLATABLE: 'STRING_TRANSLATABLE',
77+
model.base.DataTypeIEC61360.INTEGER_MEASURE: 'INTEGER_MEASURE',
78+
model.base.DataTypeIEC61360.INTEGER_COUNT: 'INTEGER_COUNT',
79+
model.base.DataTypeIEC61360.INTEGER_CURRENCY: 'INTEGER_CURRENCY',
80+
model.base.DataTypeIEC61360.REAL_MEASURE: 'REAL_MEASURE',
81+
model.base.DataTypeIEC61360.REAL_COUNT: 'REAL_COUNT',
82+
model.base.DataTypeIEC61360.REAL_CURRENCY: 'REAL_CURRENCY',
83+
model.base.DataTypeIEC61360.BOOLEAN: 'BOOLEAN',
84+
model.base.DataTypeIEC61360.IRI: 'IRI',
85+
model.base.DataTypeIEC61360.IRDI: 'IRDI',
86+
model.base.DataTypeIEC61360.RATIONAL: 'RATIONAL',
87+
model.base.DataTypeIEC61360.RATIONAL_MEASURE: 'RATIONAL_MEASURE',
88+
model.base.DataTypeIEC61360.TIME: 'TIME',
89+
model.base.DataTypeIEC61360.TIMESTAMP: 'TIMESTAMP',
90+
model.base.DataTypeIEC61360.HTML: 'HTML',
91+
model.base.DataTypeIEC61360.BLOB: 'BLOB',
92+
model.base.DataTypeIEC61360.FILE: 'FILE',
7893
}
7994

80-
IEC61360_LEVEL_TYPES: Dict[model.concept.IEC61360LevelType, str] = {
81-
model.concept.IEC61360LevelType.MIN: 'Min',
82-
model.concept.IEC61360LevelType.MAX: 'Max',
83-
model.concept.IEC61360LevelType.NOM: 'Nom',
84-
model.concept.IEC61360LevelType.TYP: 'Typ',
95+
IEC61360_LEVEL_TYPES: Dict[model.base.IEC61360LevelType, str] = {
96+
model.base.IEC61360LevelType.MIN: 'min',
97+
model.base.IEC61360LevelType.NOM: 'nom',
98+
model.base.IEC61360LevelType.TYP: 'typ',
99+
model.base.IEC61360LevelType.MAX: 'max',
85100
}
86101

87-
MODELING_KIND_INVERSE: Dict[str, model.ModelingKind] = {v: k for k, v in MODELING_KIND.items()}
102+
MODELLING_KIND_INVERSE: Dict[str, model.ModellingKind] = {v: k for k, v in MODELLING_KIND.items()}
88103
ASSET_KIND_INVERSE: Dict[str, model.AssetKind] = {v: k for k, v in ASSET_KIND.items()}
89-
KEY_ELEMENTS_INVERSE: Dict[str, model.KeyElements] = {v: k for k, v in KEY_ELEMENTS.items()}
90-
KEY_TYPES_INVERSE: Dict[str, model.KeyType] = {v: k for k, v in KEY_TYPES.items()}
91-
IDENTIFIER_TYPES_INVERSE: Dict[str, model.IdentifierType] = {v: k for k, v in IDENTIFIER_TYPES.items()}
104+
QUALIFIER_KIND_INVERSE: Dict[str, model.QualifierKind] = {v: k for k, v in QUALIFIER_KIND.items()}
105+
DIRECTION_INVERSE: Dict[str, model.Direction] = {v: k for k, v in DIRECTION.items()}
106+
STATE_OF_EVENT_INVERSE: Dict[str, model.StateOfEvent] = {v: k for k, v in STATE_OF_EVENT.items()}
107+
REFERENCE_TYPES_INVERSE: Dict[str, Type[model.Reference]] = {v: k for k, v in REFERENCE_TYPES.items()}
108+
KEY_TYPES_INVERSE: Dict[str, model.KeyTypes] = {v: k for k, v in KEY_TYPES.items()}
92109
ENTITY_TYPES_INVERSE: Dict[str, model.EntityType] = {v: k for k, v in ENTITY_TYPES.items()}
93-
IEC61360_DATA_TYPES_INVERSE: Dict[str, model.concept.IEC61360DataType] = {v: k for k, v in IEC61360_DATA_TYPES.items()}
94-
IEC61360_LEVEL_TYPES_INVERSE: Dict[str, model.concept.IEC61360LevelType] = \
110+
IEC61360_DATA_TYPES_INVERSE: Dict[str, model.base.DataTypeIEC61360] = {v: k for k, v in IEC61360_DATA_TYPES.items()}
111+
IEC61360_LEVEL_TYPES_INVERSE: Dict[str, model.base.IEC61360LevelType] = \
95112
{v: k for k, v in IEC61360_LEVEL_TYPES.items()}
96113

97-
KEY_ELEMENTS_CLASSES_INVERSE: Dict[model.KeyElements, Type[model.Referable]] = \
98-
{v: k for k, v in model.KEY_ELEMENTS_CLASSES.items()}
114+
KEY_TYPES_CLASSES_INVERSE: Dict[model.KeyTypes, Type[model.Referable]] = \
115+
{v: k for k, v in model.KEY_TYPES_CLASSES.items()}

0 commit comments

Comments
 (0)