aas-standard-parser 0.2.1__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. aas_standard_parser-0.3.1/PKG-INFO +92 -0
  2. aas_standard_parser-0.3.1/README.md +58 -0
  3. aas_standard_parser-0.3.1/aas_standard_parser/__init__.py +44 -0
  4. aas_standard_parser-0.3.1/aas_standard_parser/aas_parser.py +24 -0
  5. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser/aimc_parser.py +1 -50
  6. aas_standard_parser-0.3.1/aas_standard_parser/classes/aimc_parser_classes.py +52 -0
  7. aas_standard_parser-0.3.1/aas_standard_parser/reference_helpers.py +38 -0
  8. aas_standard_parser-0.3.1/aas_standard_parser/submodel_json_parser.py +36 -0
  9. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser/submodel_parser.py +4 -17
  10. aas_standard_parser-0.3.1/aas_standard_parser/utils.py +50 -0
  11. aas_standard_parser-0.3.1/aas_standard_parser/version_check.py +28 -0
  12. aas_standard_parser-0.3.1/aas_standard_parser.egg-info/PKG-INFO +92 -0
  13. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser.egg-info/SOURCES.txt +4 -0
  14. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/pyproject.toml +2 -2
  15. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/tests/test_aimc_parser.py +5 -3
  16. aas_standard_parser-0.2.1/PKG-INFO +0 -36
  17. aas_standard_parser-0.2.1/README.md +0 -2
  18. aas_standard_parser-0.2.1/aas_standard_parser/__init__.py +0 -19
  19. aas_standard_parser-0.2.1/aas_standard_parser/reference_helpers.py +0 -12
  20. aas_standard_parser-0.2.1/aas_standard_parser/utils.py +0 -25
  21. aas_standard_parser-0.2.1/aas_standard_parser.egg-info/PKG-INFO +0 -36
  22. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/LICENSE +0 -0
  23. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser/aid_parser.py +0 -0
  24. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser/collection_helpers.py +0 -0
  25. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser/demo/demo_process.py +0 -0
  26. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser/demo/logging_handler.py +0 -0
  27. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser.egg-info/dependency_links.txt +0 -0
  28. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser.egg-info/requires.txt +0 -0
  29. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/aas_standard_parser.egg-info/top_level.txt +0 -0
  30. {aas_standard_parser-0.2.1 → aas_standard_parser-0.3.1}/setup.cfg +0 -0
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: aas-standard-parser
3
+ Version: 0.3.1
4
+ Summary: Some auxiliary functions for parsing standard submodels
5
+ Author-email: Daniel Klein <daniel.klein@em.ag>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Fluid4.0
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/fluid40/aas-standard-parser
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: typing>=3.7.4.3
32
+ Requires-Dist: basyx-python-sdk>=1.2.1
33
+ Dynamic: license-file
34
+
35
+ # aas-standard-parser
36
+
37
+ <div align="center">
38
+ <!-- change this to your projects logo if you have on.
39
+ If you don't have one it might be worth trying chatgpt dall-e to create one for you...
40
+ -->
41
+ <img src="docs/assets/fluid_logo.svg" alt="aas_standard_parser" width=500 />
42
+ </div>
43
+
44
+ ---
45
+
46
+ [![License: MIT](https://img.shields.io/badge/license-MIT-%23f8a602?label=License&labelColor=%23992b2e)](LICENSE)
47
+ [![CI](https://github.com/fluid40/aas-standard-parser/actions/workflows/CI.yml/badge.svg?branch=main&cache-bust=1)](https://github.com/fluid40/aas-standard-parser/actions)
48
+ [![PyPI version](https://img.shields.io/pypi/v/aas-standard-parser.svg)](https://pypi.org/project/aas-standard-parser/)
49
+
50
+
51
+ This project provides tools for parsing and handling Asset Administration Shell (AAS) standard submodels, with a focus on AID and AIMC submodels. It enables:
52
+
53
+ - Extraction, interpretation, and mapping of submodel elements and their properties
54
+ - Working with references, semantic IDs, and submodel element collections
55
+ - Representation and processing of mapping configurations and source-sink relations
56
+ - Structured and colored logging, including log file management
57
+
58
+ These components enable efficient parsing, transformation, and analysis of AAS submodels in Python-based workflows.
59
+ > **Note:** Most functions in this project utilize the [python aas sdk framework](https://github.com/aas-core-works/aas-core3.0-python) for parsing and handling AAS submodels, ensuring compatibility with the official AAS data models and structures.
60
+ ---
61
+
62
+ ## Provided Parsers
63
+
64
+ - **AID Parser**: Parses AID submodels to extract interface descriptions, properties, and security/authentication details.
65
+ - **AIMC Parser**: Parses AIMC submodels to extract and process mapping configurations and source-sink relations.
66
+ - **AAS Parser**: Utilities to extract submodel IDs from an Asset Administration Shell.
67
+ - **Submodel Parser**: Helpers to retrieve submodel elements by semantic ID or by path within a submodel.
68
+
69
+ ## Helper Modules
70
+
71
+ - **Collection Helpers**: Functions to search and filter submodel elements by semantic ID, idShort, or supplemental semantic ID within collections.
72
+ - **Reference Helpers**: Utilities for working with references, such as constructing idShort paths and extracting values from reference keys.
73
+ - **Utilities**: General utility functions, including loading a submodel from a file.
74
+
75
+ ---
76
+
77
+ ## API References
78
+ - AID Parser
79
+ - AIMC Parser
80
+ - [AAS Parser](docs/api_references/api_aas_parser.md)
81
+ - [Submodel Parser](docs/api_references/api_submodel_parser.md)
82
+ - Collection Helpers
83
+ - [Reference Helpers](docs/api_references/api_reference_helpers.md)
84
+ - [Utilities](docs/api_references/api_utils.md)
85
+
86
+ ## Resources
87
+
88
+ 🤖 [Releases](http://github.com/fluid40/aas-standard-parser/releases)
89
+
90
+ 📦 [Pypi Packages](https://pypi.org/project/aas-standard-parser/)
91
+
92
+ 📜 [MIT License](LICENSE)
@@ -0,0 +1,58 @@
1
+ # aas-standard-parser
2
+
3
+ <div align="center">
4
+ <!-- change this to your projects logo if you have on.
5
+ If you don't have one it might be worth trying chatgpt dall-e to create one for you...
6
+ -->
7
+ <img src="docs/assets/fluid_logo.svg" alt="aas_standard_parser" width=500 />
8
+ </div>
9
+
10
+ ---
11
+
12
+ [![License: MIT](https://img.shields.io/badge/license-MIT-%23f8a602?label=License&labelColor=%23992b2e)](LICENSE)
13
+ [![CI](https://github.com/fluid40/aas-standard-parser/actions/workflows/CI.yml/badge.svg?branch=main&cache-bust=1)](https://github.com/fluid40/aas-standard-parser/actions)
14
+ [![PyPI version](https://img.shields.io/pypi/v/aas-standard-parser.svg)](https://pypi.org/project/aas-standard-parser/)
15
+
16
+
17
+ This project provides tools for parsing and handling Asset Administration Shell (AAS) standard submodels, with a focus on AID and AIMC submodels. It enables:
18
+
19
+ - Extraction, interpretation, and mapping of submodel elements and their properties
20
+ - Working with references, semantic IDs, and submodel element collections
21
+ - Representation and processing of mapping configurations and source-sink relations
22
+ - Structured and colored logging, including log file management
23
+
24
+ These components enable efficient parsing, transformation, and analysis of AAS submodels in Python-based workflows.
25
+ > **Note:** Most functions in this project utilize the [python aas sdk framework](https://github.com/aas-core-works/aas-core3.0-python) for parsing and handling AAS submodels, ensuring compatibility with the official AAS data models and structures.
26
+ ---
27
+
28
+ ## Provided Parsers
29
+
30
+ - **AID Parser**: Parses AID submodels to extract interface descriptions, properties, and security/authentication details.
31
+ - **AIMC Parser**: Parses AIMC submodels to extract and process mapping configurations and source-sink relations.
32
+ - **AAS Parser**: Utilities to extract submodel IDs from an Asset Administration Shell.
33
+ - **Submodel Parser**: Helpers to retrieve submodel elements by semantic ID or by path within a submodel.
34
+
35
+ ## Helper Modules
36
+
37
+ - **Collection Helpers**: Functions to search and filter submodel elements by semantic ID, idShort, or supplemental semantic ID within collections.
38
+ - **Reference Helpers**: Utilities for working with references, such as constructing idShort paths and extracting values from reference keys.
39
+ - **Utilities**: General utility functions, including loading a submodel from a file.
40
+
41
+ ---
42
+
43
+ ## API References
44
+ - AID Parser
45
+ - AIMC Parser
46
+ - [AAS Parser](docs/api_references/api_aas_parser.md)
47
+ - [Submodel Parser](docs/api_references/api_submodel_parser.md)
48
+ - Collection Helpers
49
+ - [Reference Helpers](docs/api_references/api_reference_helpers.md)
50
+ - [Utilities](docs/api_references/api_utils.md)
51
+
52
+ ## Resources
53
+
54
+ 🤖 [Releases](http://github.com/fluid40/aas-standard-parser/releases)
55
+
56
+ 📦 [Pypi Packages](https://pypi.org/project/aas-standard-parser/)
57
+
58
+ 📜 [MIT License](LICENSE)
@@ -0,0 +1,44 @@
1
+ """AAS Standard parser Package."""
2
+
3
+ import importlib.metadata
4
+ from datetime import datetime, timezone
5
+
6
+ from aas_standard_parser import (
7
+ aas_parser,
8
+ aid_parser,
9
+ aimc_parser,
10
+ collection_helpers,
11
+ reference_helpers,
12
+ submodel_json_parser,
13
+ submodel_parser,
14
+ utils,
15
+ )
16
+ from aas_standard_parser.aid_parser import AIDParser
17
+ from aas_standard_parser.version_check import check_for_update
18
+
19
+ __copyright__ = f"Copyright (C) {datetime.now(tz=timezone.utc).year} Fluid 4.0. All rights reserved."
20
+ __author__ = "Daniel Klein, Celina Adelhardt, Tom Gneuß"
21
+
22
+ try:
23
+ __license__ = "MIT"
24
+ __version__ = importlib.metadata.version(__name__)
25
+ except importlib.metadata.PackageNotFoundError:
26
+ __version__ = "0.0.0-dev"
27
+
28
+ __project__ = "aas-standard-parser"
29
+ __package__ = "aas-standard-parser"
30
+
31
+
32
+ check_for_update()
33
+
34
+ __all__ = [
35
+ "AIDParser",
36
+ "aas_parser",
37
+ "aid_parser",
38
+ "aimc_parser",
39
+ "collection_helpers",
40
+ "reference_helpers",
41
+ "submodel_json_parser",
42
+ "submodel_parser",
43
+ "utils",
44
+ ]
@@ -0,0 +1,24 @@
1
+ """Module for parsing AAS."""
2
+
3
+ import logging
4
+
5
+ from basyx.aas import model
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ def get_submodel_ids(shell: model.AssetAdministrationShell) -> list[str]:
11
+ """Get all IDs from the submodels referenced in the given AAS.
12
+
13
+ :param shell: The Asset Administration Shell to extract submodel IDs from.
14
+ :return: A list of submodel IDs referenced in the AAS.
15
+ """
16
+ submodel_ids = []
17
+ for submodel in shell.submodel:
18
+ if len(submodel.key) < 1 or submodel.key[0].type != model.KeyTypes.SUBMODEL:
19
+ logger.warning(f"Submodel reference {submodel} does not start with SUBMODEL key type.")
20
+ continue
21
+
22
+ submodel_ids.append(submodel.key[0].value)
23
+
24
+ return submodel_ids
@@ -1,64 +1,15 @@
1
1
  """Parser for Mapping Configurations in AIMC Submodel."""
2
2
 
3
- import json
4
3
  import logging
5
- from dataclasses import field
6
4
 
7
- import basyx.aas.adapter.json
8
5
  from basyx.aas import model
9
6
 
10
7
  import aas_standard_parser.collection_helpers as ch
8
+ from aas_standard_parser.classes.aimc_parser_classes import MappingConfiguration, MappingConfigurations, ReferenceProperties, SourceSinkRelation
11
9
 
12
10
  logger = logging.getLogger(__name__)
13
11
 
14
12
 
15
- class ReferenceProperties:
16
- """Class representing properties of a reference in the mapping configuration."""
17
-
18
- reference: model.ExternalReference = field(metadata={"description": "Reference to the property in the submodel."})
19
- submodel_id: str = field(metadata={"description": "Identifier of the submodel used by the reference."})
20
- property_name: str = field(metadata={"description": "Name of the mapped property."})
21
- parent_path: list[str] = field(metadata={"description": "List of idShorts representing the parent path of the reference."})
22
-
23
-
24
- class SourceSinkRelation:
25
- """Class representing a source-sink relation in the mapping configuration."""
26
-
27
- source_properties: ReferenceProperties = field(metadata={"description": "Properties of the source reference."})
28
- sink_properties: ReferenceProperties = field(metadata={"description": "Properties of the sink reference."})
29
-
30
- def source_as_dict(self) -> dict:
31
- """Convert the source reference to a dictionary.
32
-
33
- :return: The source reference as a dictionary.
34
- """
35
- dict_string = json.dumps(self.source_properties.reference, cls=basyx.aas.adapter.json.AASToJsonEncoder)
36
- dict_string = dict_string.replace("GlobalReference", "Submodel").replace("FragmentReference", "SubmodelElementCollection")
37
- return json.loads(dict_string)
38
-
39
- def sink_as_dict(self) -> dict:
40
- """Convert the sink reference to a dictionary.
41
-
42
- :return: The sink reference as a dictionary.
43
- """
44
- return json.dumps(self.sink_properties.reference, cls=basyx.aas.adapter.json.AASToJsonEncoder)
45
-
46
-
47
- class MappingConfiguration:
48
- """Class representing a mapping configuration."""
49
-
50
- interface_reference: model.ReferenceElement = field(metadata={"description": "Reference to the interface in the AID submodel."})
51
- aid_submodel_id: str = field(metadata={"description": "Identifier of the AID submodel used by the interface reference."})
52
- source_sink_relations: list[SourceSinkRelation] = field(metadata={"description": "List of source-sink relations in the mapping configuration."})
53
-
54
-
55
- class MappingConfigurations:
56
- """Class representing mapping configurations from AIMC submodel."""
57
-
58
- configurations: list[MappingConfiguration] = field(metadata={"description": "List of mapping configurations."})
59
- aid_submodel_ids: list[str] = field(metadata={"description": "List of AID submodel IDs used in the mapping configurations."})
60
-
61
-
62
13
  def get_mapping_configuration_root_element(aimc_submodel: model.Submodel) -> model.SubmodelElementCollection | None:
63
14
  """Get the mapping configuration root submodel element collection from the AIMC submodel.
64
15
 
@@ -0,0 +1,52 @@
1
+ import json
2
+ from dataclasses import field
3
+
4
+ import basyx.aas.adapter.json
5
+ from basyx.aas import model
6
+
7
+
8
+ class ReferenceProperties:
9
+ """Class representing properties of a reference in the mapping configuration."""
10
+
11
+ reference: model.ExternalReference = field(metadata={"description": "Reference to the property in the submodel."})
12
+ submodel_id: str = field(metadata={"description": "Identifier of the submodel used by the reference."})
13
+ property_name: str = field(metadata={"description": "Name of the mapped property."})
14
+ parent_path: list[str] = field(metadata={"description": "List of idShorts representing the parent path of the reference."})
15
+
16
+
17
+ class SourceSinkRelation:
18
+ """Class representing a source-sink relation in the mapping configuration."""
19
+
20
+ source_properties: ReferenceProperties = field(metadata={"description": "Properties of the source reference."})
21
+ sink_properties: ReferenceProperties = field(metadata={"description": "Properties of the sink reference."})
22
+
23
+ def source_reference_as_dict(self) -> dict:
24
+ """Convert the source reference to a dictionary.
25
+
26
+ :return: The source reference as a dictionary.
27
+ """
28
+ dict_string = json.dumps(self.source_properties.reference, cls=basyx.aas.adapter.json.AASToJsonEncoder)
29
+ dict_string = dict_string.replace("GlobalReference", "Submodel").replace("FragmentReference", "SubmodelElementCollection")
30
+ return json.loads(dict_string)
31
+
32
+ def sink_reference_as_dict(self) -> dict:
33
+ """Convert the sink reference to a dictionary.
34
+
35
+ :return: The sink reference as a dictionary.
36
+ """
37
+ return json.loads(json.dumps(self.sink_properties.reference, cls=basyx.aas.adapter.json.AASToJsonEncoder))
38
+
39
+
40
+ class MappingConfiguration:
41
+ """Class representing a mapping configuration."""
42
+
43
+ interface_reference: model.ReferenceElement = field(metadata={"description": "Reference to the interface in the AID submodel."})
44
+ aid_submodel_id: str = field(metadata={"description": "Identifier of the AID submodel used by the interface reference."})
45
+ source_sink_relations: list[SourceSinkRelation] = field(metadata={"description": "List of source-sink relations in the mapping configuration."})
46
+
47
+
48
+ class MappingConfigurations:
49
+ """Class representing mapping configurations from AIMC submodel."""
50
+
51
+ configurations: list[MappingConfiguration] = field(metadata={"description": "List of mapping configurations."})
52
+ aid_submodel_ids: list[str] = field(metadata={"description": "List of AID submodel IDs used in the mapping configurations."})
@@ -0,0 +1,38 @@
1
+ """Helper functions for working with ModelReference objects in the AAS standard parser."""
2
+
3
+ from basyx.aas.model import ModelReference
4
+
5
+
6
+ def construct_id_short_path_from_reference(reference: ModelReference) -> str:
7
+ """Constructs an idShort path from the given ModelReference.
8
+
9
+ :param reference: The ModelReference to construct the idShort path from.
10
+ :return: The constructed idShort path as a string.
11
+ """
12
+ id_short_path: str = ""
13
+
14
+ # start from the second Key and omit the Identifiable at the beginning of the list
15
+ for key in reference.key[1:]:
16
+ id_short_path += key.value + "."
17
+
18
+ # get rid of the trailing dot
19
+ return id_short_path[:-1]
20
+
21
+
22
+ def get_values_from_keys(reference: ModelReference) -> list[str]:
23
+ """Returns the values from all keys in reference as list.
24
+
25
+ :param reference: reference to extract values from
26
+ :return: list of values from all keys in the reference
27
+ """
28
+ return [key.value for key in reference.key]
29
+
30
+
31
+ def get_value_from_key_at_index(reference: ModelReference, index: int) -> str:
32
+ """Returns the value from the key at the given index in reference.
33
+
34
+ :param reference: reference to extract value from
35
+ :param index: index of the key to get the value from
36
+ :return: value from the key at the given index
37
+ """
38
+ return reference.key[index].value
@@ -0,0 +1,36 @@
1
+ """Module for parsing submodels JSON data."""
2
+
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ def get_value_from_semantic_id_by_index(submodel_data: dict, index: int = 0) -> str | None:
9
+ """Retrieve the value from the semantic ID from a submodel JSON dictionary by index.
10
+
11
+ :param submodel_data: The submodel data as a dictionary.
12
+ :param index: The index to access if the element is a list or collection, defaults to 0.
13
+ :return: The value of the found submodel element or None if not found.
14
+ """
15
+ if "semanticId" not in submodel_data:
16
+ logger.debug(f"Submodel '{submodel_data}' has no semantic ID")
17
+ return None
18
+
19
+ sm_semantic_id = submodel_data.get("semanticId", {})
20
+ if "keys" not in sm_semantic_id or len(sm_semantic_id["keys"]) == 0:
21
+ logger.debug(f"Submodel '{submodel_data}' has no semantic ID keys")
22
+ return None
23
+
24
+ keys = sm_semantic_id.get("keys", [])
25
+
26
+ if len(keys) < index + 1:
27
+ logger.debug(f"Submodel '{submodel_data}' has no semantic ID key at index {index}")
28
+ return None
29
+
30
+ key = keys[index]
31
+
32
+ if "value" not in key:
33
+ logger.debug(f"Submodel '{submodel_data}' has no semantic ID value")
34
+ return None
35
+
36
+ return key["value"]
@@ -3,32 +3,19 @@
3
3
  import logging
4
4
 
5
5
  from basyx.aas import model
6
- from basyx.aas.model import NamespaceSet, SubmodelElement
7
-
8
- from aas_standard_parser import collection_helpers
9
6
 
10
7
  logger = logging.getLogger(__name__)
11
8
 
12
9
 
13
- def get_element_by_semantic_id(collection: NamespaceSet[SubmodelElement], semantic_id: str) -> SubmodelElement | None:
14
- """Get an element from parent collection by its semantic ID (not recursive).
15
-
16
- :param parent: parent collection to search within
17
- :param semantic_id: semantic ID to search for
18
- :return: the found submodel element or None if not found
19
- """
20
- return collection_helpers.find_by_semantic_id(collection, semantic_id)
21
-
22
-
23
- def get_submodel_element_by_path(submodel: model.Submodel, path: str) -> model.SubmodelElement:
24
- """Returns a specific submodel element from the submodel at a specific path.
10
+ def get_submodel_element_by_id_short_path(submodel: model.Submodel, id_short_path: str) -> model.SubmodelElement:
11
+ """Retrieve a specific submodel element from the submodel at a specific idShort path.
25
12
 
26
13
  :param submodel: The submodel to search within.
27
- :param path: IdShort path to the submodel element (dot-separated), e.g., "Element1.Element2[0].Element3".
14
+ :param id_short_path: IdShort path to the submodel element (dot-separated), e.g., "Element1.Element2[0].Element3".
28
15
  :return: The found submodel element or None if not found.
29
16
  """
30
17
  # Split the path by '.' and traverse the structure
31
- parts = path.split(".")
18
+ parts = id_short_path.split(".")
32
19
  current_elements = submodel.submodel_element
33
20
  part_index = 0
34
21
  for part in parts:
@@ -0,0 +1,50 @@
1
+ """Utility functions for AAS standard parser."""
2
+
3
+ import json
4
+ import logging
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import basyx.aas.adapter.json
9
+ from basyx.aas import model
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ def create_submodel_from_file(file_path: str) -> model.Submodel:
15
+ """Loads a Submodel structure from a given JSON file and converts it into a model.Submodel object from the python SDK framework.
16
+
17
+ :param file_path: Path to the JSON file containing the Submodel structure.
18
+ :return: A model.Submodel object representing the loaded Submodel structure.
19
+ """
20
+ file = Path(file_path)
21
+ if not file.exists():
22
+ raise FileNotFoundError(f"Submodel structure file not found: {file}")
23
+
24
+ template_data = {}
25
+
26
+ # Load the template JSON file
27
+ with file.open("r", encoding="utf-8") as f:
28
+ template_data = json.load(f)
29
+
30
+ # Load the template JSON into a Submodel object
31
+ return _convert_to_object(template_data)
32
+
33
+
34
+ def _convert_to_object(content: dict) -> Any | None:
35
+ """Convert a dictionary to a BaSyx SDK framework object.
36
+
37
+ :param content: dictionary to convert
38
+ :return: BaSyx SDK framework object or None
39
+ """
40
+ if not content or len(content) == 0:
41
+ logger.debug("Empty content provided for conversion to object.")
42
+ return None
43
+
44
+ try:
45
+ dict_string = json.dumps(content)
46
+ return json.loads(dict_string, cls=basyx.aas.adapter.json.json_deserialization.AASFromJsonDecoder)
47
+ except Exception as e:
48
+ logger.error(f"Decoding error: {e}")
49
+ logger.error(f"In JSON: {content}")
50
+ return None
@@ -0,0 +1,28 @@
1
+ """Utility functions for version checking."""
2
+
3
+ import importlib.metadata
4
+ import logging
5
+
6
+ import requests
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ def check_for_update(package_name="aas-standard-parser"):
12
+ """Check for updates of the package on PyPI.
13
+
14
+ :param package_name: The name of the package to check for updates, defaults to "aas-standard-parser"
15
+ """
16
+ try:
17
+ current_version = importlib.metadata.version(package_name)
18
+ pypi_url = f"https://pypi.org/pypi/{package_name}/json"
19
+ latest_version = requests.get(pypi_url, timeout=3).json()["info"]["version"]
20
+
21
+ if current_version != latest_version:
22
+ print(
23
+ f"⚠️ A new version for package '{package_name}' is available: "
24
+ f"{latest_version} (currently installed: {current_version}). "
25
+ f"Use the following command to update the package: pip install --upgrade {package_name}"
26
+ )
27
+ except Exception as exc:
28
+ logger.exception(f"Exception occurred while checking for package update: {exc}")
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: aas-standard-parser
3
+ Version: 0.3.1
4
+ Summary: Some auxiliary functions for parsing standard submodels
5
+ Author-email: Daniel Klein <daniel.klein@em.ag>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Fluid4.0
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/fluid40/aas-standard-parser
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: typing>=3.7.4.3
32
+ Requires-Dist: basyx-python-sdk>=1.2.1
33
+ Dynamic: license-file
34
+
35
+ # aas-standard-parser
36
+
37
+ <div align="center">
38
+ <!-- change this to your projects logo if you have on.
39
+ If you don't have one it might be worth trying chatgpt dall-e to create one for you...
40
+ -->
41
+ <img src="docs/assets/fluid_logo.svg" alt="aas_standard_parser" width=500 />
42
+ </div>
43
+
44
+ ---
45
+
46
+ [![License: MIT](https://img.shields.io/badge/license-MIT-%23f8a602?label=License&labelColor=%23992b2e)](LICENSE)
47
+ [![CI](https://github.com/fluid40/aas-standard-parser/actions/workflows/CI.yml/badge.svg?branch=main&cache-bust=1)](https://github.com/fluid40/aas-standard-parser/actions)
48
+ [![PyPI version](https://img.shields.io/pypi/v/aas-standard-parser.svg)](https://pypi.org/project/aas-standard-parser/)
49
+
50
+
51
+ This project provides tools for parsing and handling Asset Administration Shell (AAS) standard submodels, with a focus on AID and AIMC submodels. It enables:
52
+
53
+ - Extraction, interpretation, and mapping of submodel elements and their properties
54
+ - Working with references, semantic IDs, and submodel element collections
55
+ - Representation and processing of mapping configurations and source-sink relations
56
+ - Structured and colored logging, including log file management
57
+
58
+ These components enable efficient parsing, transformation, and analysis of AAS submodels in Python-based workflows.
59
+ > **Note:** Most functions in this project utilize the [python aas sdk framework](https://github.com/aas-core-works/aas-core3.0-python) for parsing and handling AAS submodels, ensuring compatibility with the official AAS data models and structures.
60
+ ---
61
+
62
+ ## Provided Parsers
63
+
64
+ - **AID Parser**: Parses AID submodels to extract interface descriptions, properties, and security/authentication details.
65
+ - **AIMC Parser**: Parses AIMC submodels to extract and process mapping configurations and source-sink relations.
66
+ - **AAS Parser**: Utilities to extract submodel IDs from an Asset Administration Shell.
67
+ - **Submodel Parser**: Helpers to retrieve submodel elements by semantic ID or by path within a submodel.
68
+
69
+ ## Helper Modules
70
+
71
+ - **Collection Helpers**: Functions to search and filter submodel elements by semantic ID, idShort, or supplemental semantic ID within collections.
72
+ - **Reference Helpers**: Utilities for working with references, such as constructing idShort paths and extracting values from reference keys.
73
+ - **Utilities**: General utility functions, including loading a submodel from a file.
74
+
75
+ ---
76
+
77
+ ## API References
78
+ - AID Parser
79
+ - AIMC Parser
80
+ - [AAS Parser](docs/api_references/api_aas_parser.md)
81
+ - [Submodel Parser](docs/api_references/api_submodel_parser.md)
82
+ - Collection Helpers
83
+ - [Reference Helpers](docs/api_references/api_reference_helpers.md)
84
+ - [Utilities](docs/api_references/api_utils.md)
85
+
86
+ ## Resources
87
+
88
+ 🤖 [Releases](http://github.com/fluid40/aas-standard-parser/releases)
89
+
90
+ 📦 [Pypi Packages](https://pypi.org/project/aas-standard-parser/)
91
+
92
+ 📜 [MIT License](LICENSE)
@@ -2,17 +2,21 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  aas_standard_parser/__init__.py
5
+ aas_standard_parser/aas_parser.py
5
6
  aas_standard_parser/aid_parser.py
6
7
  aas_standard_parser/aimc_parser.py
7
8
  aas_standard_parser/collection_helpers.py
8
9
  aas_standard_parser/reference_helpers.py
10
+ aas_standard_parser/submodel_json_parser.py
9
11
  aas_standard_parser/submodel_parser.py
10
12
  aas_standard_parser/utils.py
13
+ aas_standard_parser/version_check.py
11
14
  aas_standard_parser.egg-info/PKG-INFO
12
15
  aas_standard_parser.egg-info/SOURCES.txt
13
16
  aas_standard_parser.egg-info/dependency_links.txt
14
17
  aas_standard_parser.egg-info/requires.txt
15
18
  aas_standard_parser.egg-info/top_level.txt
19
+ aas_standard_parser/classes/aimc_parser_classes.py
16
20
  aas_standard_parser/demo/demo_process.py
17
21
  aas_standard_parser/demo/logging_handler.py
18
22
  tests/test_aimc_parser.py
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aas-standard-parser"
7
- version = "0.2.1"
7
+ version = "0.3.1"
8
8
  description = "Some auxiliary functions for parsing standard submodels"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
11
11
  authors = [{ name = "Daniel Klein", email = "daniel.klein@em.ag" }]
12
12
  dependencies = ["typing>=3.7.4.3", "basyx-python-sdk>=1.2.1"]
13
13
  [project.urls]
14
- Homepage = "https://github.com/fluid40/aas-http-client"
14
+ Homepage = "https://github.com/fluid40/aas-standard-parser"
15
15
 
16
16
  [tool.commitizen]
17
17
  name = "cz_conventional_commits"
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  from basyx.aas import model
3
3
 
4
- from aas_standard_parser.aimc_parser import MappingConfiguration, SourceSinkRelation, ReferenceProperties
4
+ from aas_standard_parser.classes.aimc_parser_classes import MappingConfiguration, SourceSinkRelation, ReferenceProperties
5
5
  import aas_standard_parser.aimc_parser as aimc_parser
6
6
  from aas_standard_parser.utils import create_submodel_from_file
7
7
 
@@ -120,10 +120,12 @@ def _check_relations_sink(reference_properties: ReferenceProperties):
120
120
 
121
121
  def _check_relation_methods(relation: SourceSinkRelation):
122
122
  # test to_json methods
123
- source_json = relation.source_as_dict()
123
+ source_json = relation.source_reference_as_dict()
124
+ assert isinstance(source_json, dict)
124
125
  assert source_json is not None
125
126
  assert "type" in source_json
126
127
 
127
- sink_json = relation.sink_as_dict()
128
+ sink_json = relation.sink_reference_as_dict()
129
+ assert isinstance(sink_json, dict)
128
130
  assert sink_json is not None
129
131
  assert "type" in sink_json
@@ -1,36 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: aas-standard-parser
3
- Version: 0.2.1
4
- Summary: Some auxiliary functions for parsing standard submodels
5
- Author-email: Daniel Klein <daniel.klein@em.ag>
6
- License: MIT License
7
-
8
- Copyright (c) 2025 Fluid4.0
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
-
28
- Project-URL: Homepage, https://github.com/fluid40/aas-http-client
29
- Description-Content-Type: text/markdown
30
- License-File: LICENSE
31
- Requires-Dist: typing>=3.7.4.3
32
- Requires-Dist: basyx-python-sdk>=1.2.1
33
- Dynamic: license-file
34
-
35
- # aas-standard-parser
36
- Some auxiliary functions for parsing standard submodels
@@ -1,2 +0,0 @@
1
- # aas-standard-parser
2
- Some auxiliary functions for parsing standard submodels
@@ -1,19 +0,0 @@
1
- import importlib.metadata
2
- from datetime import datetime
3
-
4
- # TODO: introduce MIT license
5
- __copyright__ = f"Copyright (C) {datetime.now().year} :em engineering methods AG. All rights reserved."
6
- __author__ = "Daniel Klein, Celina Adelhardt, Tom Gneuß"
7
-
8
- try:
9
- __version__ = importlib.metadata.version(__name__)
10
- except importlib.metadata.PackageNotFoundError:
11
- __version__ = "0.0.0-dev"
12
-
13
- __project__ = "aas-standard-parser"
14
- __package__ = "aas-standard-parser"
15
-
16
- from aas_standard_parser import aimc_parser
17
- from aas_standard_parser.aid_parser import AIDParser
18
-
19
- __all__ = ["AIDParser", "aimc_parser"]
@@ -1,12 +0,0 @@
1
- from basyx.aas.model import ModelReference
2
-
3
-
4
- def construct_idshort_path_from_reference(reference: ModelReference) -> str:
5
- idshort_path: str = ""
6
-
7
- # start from the second Key and omit the Identifiable at the beginning of the list
8
- for key in reference.key[1:]:
9
- idshort_path += (key.value + ".")
10
-
11
- # get rid of the trailing dot
12
- return idshort_path[:-1]
@@ -1,25 +0,0 @@
1
- import json
2
- from pathlib import Path
3
-
4
- from aas_http_client import sdk_tools
5
- from basyx.aas import model
6
-
7
-
8
- def create_submodel_from_file(file_path: str) -> model.Submodel:
9
- """Creates a Submodel from a given file path.
10
-
11
- :param file_path: Path to the file containing the submodel data.
12
- :return: The created Submodel object.
13
- """
14
- file = Path(file_path)
15
- if not file.exists():
16
- raise FileNotFoundError(f"Submodel template file not found: {file}")
17
-
18
- template_data = {}
19
-
20
- # Load the template JSON file
21
- with open(file, "r", encoding="utf-8") as f:
22
- template_data = json.load(f)
23
-
24
- # Load the template JSON into a Submodel object
25
- return sdk_tools.convert_to_object(template_data)
@@ -1,36 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: aas-standard-parser
3
- Version: 0.2.1
4
- Summary: Some auxiliary functions for parsing standard submodels
5
- Author-email: Daniel Klein <daniel.klein@em.ag>
6
- License: MIT License
7
-
8
- Copyright (c) 2025 Fluid4.0
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
-
28
- Project-URL: Homepage, https://github.com/fluid40/aas-http-client
29
- Description-Content-Type: text/markdown
30
- License-File: LICENSE
31
- Requires-Dist: typing>=3.7.4.3
32
- Requires-Dist: basyx-python-sdk>=1.2.1
33
- Dynamic: license-file
34
-
35
- # aas-standard-parser
36
- Some auxiliary functions for parsing standard submodels