Skip to content

Commit 6fcb36b

Browse files
committed
Merge branch 'FixSmtNameplate' into main
2 parents 89a36e0 + dfe6c66 commit 6fcb36b

File tree

2 files changed

+45
-22
lines changed

2 files changed

+45
-22
lines changed

aas_test_engines/test_cases/v3_0/parse_submodel.py

+35-13
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@
22
from .adapter import AdapterPath
33

44
from aas_test_engines.result import AasTestResult, Level
5-
from typing import List, Dict, Optional, Tuple, Union
5+
from typing import List, Dict, Tuple, Union
66
from collections import defaultdict
77
from dataclasses import is_dataclass, fields
88
from enum import Enum
9+
import datetime
910

1011
INVALID = object()
1112
LangString = Dict[str, str]
1213

1314

15+
def to_camel_case(s: str) -> str:
16+
return "".join(s.title().split('_'))
17+
18+
1419
def _unwrap(cls) -> Tuple[int, int, type]:
1520
try:
1621
origin = cls.__origin__
@@ -45,21 +50,34 @@ def _parse_string(root_result: AasTestResult, element: SubmodelElement, path: Ad
4550
if not isinstance(element, Property):
4651
root_result.append(AasTestResult(f"Cannot convert to string: must be a Property @ {path}", level=Level.ERROR))
4752
return
48-
if element.value_type != DataTypeDefXsd.string:
49-
root_result.append(AasTestResult(f"Cannot convert to string: valueType must be xs:string @ {path}", level=Level.ERROR))
50-
return
5153
if not element.value:
5254
root_result.append(AasTestResult(f"Cannot convert to string: no value @ {path}", level=Level.ERROR))
5355
return
56+
if element.value_type != DataTypeDefXsd.string:
57+
root_result.append(AasTestResult(f"Cannot convert '{element.value}' to string: valueType must be xs:string @ {path}", level=Level.ERROR))
58+
return
5459
return element.value.raw_value
5560

5661

62+
def _parse_date(root_result: AasTestResult, element: SubmodelElement, path: AdapterPath) -> str:
63+
if not isinstance(element, Property):
64+
root_result.append(AasTestResult(f"Cannot convert to date: must be a Property @ {path}", level=Level.ERROR))
65+
return
66+
if not element.value:
67+
root_result.append(AasTestResult(f"Cannot convert to date: no value @ {path}", level=Level.ERROR))
68+
return
69+
if element.value_type != DataTypeDefXsd.date:
70+
root_result.append(AasTestResult(f"Cannot convert '{element.value}' to date: valueType must be xs:date @ {path}", level=Level.ERROR))
71+
return
72+
return datetime.date.fromisoformat(element.value.raw_value)
73+
74+
5775
def _parse_lang_string(root_result: AasTestResult, element: SubmodelElement, path: AdapterPath) -> LangString:
5876
if not isinstance(element, MultiLanguageProperty):
59-
root_result.append(AasTestResult(f"Cannot convert to lang string: not a MultiLanguageProperty @ {path}"))
77+
root_result.append(AasTestResult(f"Cannot convert to lang string: not a MultiLanguageProperty @ {path}", Level.ERROR))
6078
return
6179
if not element.value:
62-
root_result.append(AasTestResult(f"Cannot convert to lang string: no value @ {path}"))
80+
root_result.append(AasTestResult(f"Cannot convert to lang string: no value @ {path}", Level.ERROR))
6381
return
6482
result: LangString = {}
6583
for i in element.value:
@@ -86,26 +104,28 @@ def _parse_elements(root_result: AasTestResult, cls, elements: List[SubmodelElem
86104
try:
87105
semantic_id = field.metadata['semantic_id']
88106
except KeyError:
89-
raise Exception(f"Field {field.name} is missing metadata 'semantic_id'")
107+
raise Exception(f"Internal error: field {field.name} is missing metadata 'semantic_id'")
90108
if semantic_id in all_semantic_ids:
91-
raise Exception(f"Duplicate metadata semantic_id {semantic_id}")
109+
raise Exception(f"Internal error: duplicate metadata semantic_id {semantic_id}")
110+
92111
all_semantic_ids.add(semantic_id)
93112

94113
min_card, max_card, field_type = _unwrap(field.type)
95114
sub_elements = elements_by_semantic_id[semantic_id]
115+
name = to_camel_case(field.name)
96116
if len(sub_elements) > max_card:
97-
root_result.append(AasTestResult(f"Field {field.name}: found {len(sub_elements)} elements with semanticId {semantic_id}, but at most {max_card} allowed", level=Level.ERROR))
117+
root_result.append(AasTestResult(f"Field {name}: found {len(sub_elements)} elements with semanticId {semantic_id}, but at most {max_card} allowed", level=Level.ERROR))
98118
field_val = INVALID
99119
elif len(sub_elements) < min_card:
100-
root_result.append(AasTestResult(f"Field {field.name}: found {len(sub_elements)} elements with semanticId {semantic_id}, but at least {min_card} required", level=Level.ERROR))
120+
root_result.append(AasTestResult(f"Field {name}: found {len(sub_elements)} elements with semanticId {semantic_id}, but at least {min_card} required", level=Level.ERROR))
101121
field_val = INVALID
102122
else:
103123
if len(sub_elements) == 0:
104124
field_val = None
105125
elif max_card == 1:
106-
field_val = _parse(field_type, sub_elements[0], root_result, path + field.name)
107-
else: # i.e. list
108-
field_val = [_parse(field_type, el, root_result, path + field.name + idx) for idx, el in enumerate(sub_elements)]
126+
field_val = _parse(field_type, sub_elements[0], root_result, path + name)
127+
else: # i.e. list
128+
field_val = [_parse(field_type, el, root_result, path + name + idx) for idx, el in enumerate(sub_elements)]
109129
args[field.name] = field_val
110130
return cls(**args)
111131

@@ -131,6 +151,8 @@ def _parse(cls, element: SubmodelElement, root_result, path: AdapterPath):
131151
return _parse_element_collection(root_result, cls, element, path)
132152
elif cls is str:
133153
return _parse_string(root_result, element, path)
154+
elif cls is datetime.date:
155+
return _parse_date(root_result, element, path)
134156
elif isinstance(cls, Enum.__class__):
135157
return _parse_enum(root_result, cls, element, path)
136158
raise NotImplementedError(

aas_test_engines/test_cases/v3_0/submodel_templates.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
from dataclasses import dataclass, field
33
from aas_test_engines.result import AasTestResult, Level
44
from enum import Enum
5+
import datetime
56

6-
from .model import Submodel, Environment
7+
from .model import Environment
78
from .parse_submodel import parse_submodel, LangString
89
from .parse import check_constraints, CheckConstraintException
910
from .adapter import AdapterPath
@@ -95,7 +96,7 @@ class IPCommunication:
9596
"semantic_id": "0173-1#02-AAQ326#002",
9697
})
9798
type_of_communication: Optional[str] = field(metadata={
98-
"semantic_id": " https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/IPCommunication/TypeOfCommunication",
99+
"semantic_id": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/IPCommunication/TypeOfCommunication",
99100
})
100101
available_time: Optional[str] = field(metadata={
101102
"semantic_id": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/AvailableTime/",
@@ -114,7 +115,7 @@ class ContactInformation:
114115
"semantic_id": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language",
115116
})
116117
time_zone: Optional[str] = field(metadata={
117-
"semantic_id": " https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/TimeZone",
118+
"semantic_id": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/TimeZone",
118119
})
119120
# TODO: Add hint: "mandatory property according to EU MachineDirective 2006/42/EC."
120121
city_town: Optional[LangString] = field(metadata={
@@ -200,10 +201,10 @@ class DigitalNameplate:
200201
"semantic_id": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation",
201202
})
202203
manufacturer_product_root: Optional[LangString] = field(metadata={
203-
"semantic_id": " 0173-1#02-AAU732#001",
204+
"semantic_id": "0173-1#02-AAU732#001",
204205
})
205206
manufacturer_product_family: Optional[LangString] = field(metadata={
206-
"semantic_id": "0173-1#02-AAU732#001",
207+
"semantic_id": "0173-1#02-AAU731#001",
207208
})
208209
manufacturer_product_type: Optional[LangString] = field(metadata={
209210
"semantic_id": "0173-1#02-AAO057#002",
@@ -220,16 +221,16 @@ class DigitalNameplate:
220221
year_of_construction: str = field(metadata={
221222
"semantic_id": "0173-1#02-AAP906#001",
222223
})
223-
date_of_manufacture: Optional[str] = field(metadata={
224+
date_of_manufacture: Optional[datetime.date] = field(metadata={
224225
"semantic_id": "0173-1#02-AAR972#002",
225226
})
226-
hardware_version: Optional[str] = field(metadata={
227+
hardware_version: Optional[LangString] = field(metadata={
227228
"semantic_id": "0173-1#02-AAN270#002",
228229
})
229-
firmware_version: Optional[str] = field(metadata={
230+
firmware_version: Optional[LangString] = field(metadata={
230231
"semantic_id": "0173-1#02-AAM985#002",
231232
})
232-
software_version: Optional[str] = field(metadata={
233+
software_version: Optional[LangString] = field(metadata={
233234
"semantic_id": "0173-1#02-AAM737#002",
234235
})
235236
country_of_origin: Optional[str] = field(metadata={

0 commit comments

Comments
 (0)