odxtools 6.7.0__py3-none-any.whl → 7.0.0__py3-none-any.whl
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.
- odxtools/basicstructure.py +106 -112
- odxtools/compumethods/createanycompumethod.py +1 -1
- odxtools/dataobjectproperty.py +3 -7
- odxtools/decodestate.py +1 -13
- odxtools/diagcodedtype.py +9 -96
- odxtools/diaglayer.py +45 -0
- odxtools/diagservice.py +12 -16
- odxtools/dopbase.py +5 -8
- odxtools/dtcdop.py +21 -19
- odxtools/dynamiclengthfield.py +30 -26
- odxtools/encodestate.py +188 -23
- odxtools/endofpdufield.py +12 -14
- odxtools/environmentdatadescription.py +13 -13
- odxtools/leadinglengthinfotype.py +25 -12
- odxtools/minmaxlengthtype.py +36 -26
- odxtools/multiplexer.py +42 -23
- odxtools/multiplexercase.py +1 -1
- odxtools/nameditemlist.py +14 -0
- odxtools/odxtypes.py +17 -0
- odxtools/parameterinfo.py +126 -40
- odxtools/parameters/codedconstparameter.py +14 -11
- odxtools/parameters/dynamicparameter.py +5 -4
- odxtools/parameters/lengthkeyparameter.py +62 -14
- odxtools/parameters/matchingrequestparameter.py +23 -11
- odxtools/parameters/nrcconstparameter.py +39 -20
- odxtools/parameters/parameter.py +29 -42
- odxtools/parameters/parameterwithdop.py +5 -8
- odxtools/parameters/physicalconstantparameter.py +12 -13
- odxtools/parameters/reservedparameter.py +5 -2
- odxtools/parameters/systemparameter.py +3 -2
- odxtools/parameters/tableentryparameter.py +3 -2
- odxtools/parameters/tablekeyparameter.py +79 -30
- odxtools/parameters/tablestructparameter.py +62 -42
- odxtools/parameters/valueparameter.py +12 -14
- odxtools/paramlengthinfotype.py +30 -22
- odxtools/request.py +9 -0
- odxtools/response.py +5 -13
- odxtools/standardlengthtype.py +51 -13
- odxtools/staticfield.py +15 -19
- odxtools/version.py +2 -2
- {odxtools-6.7.0.dist-info → odxtools-7.0.0.dist-info}/METADATA +1 -1
- {odxtools-6.7.0.dist-info → odxtools-7.0.0.dist-info}/RECORD +46 -46
- {odxtools-6.7.0.dist-info → odxtools-7.0.0.dist-info}/LICENSE +0 -0
- {odxtools-6.7.0.dist-info → odxtools-7.0.0.dist-info}/WHEEL +0 -0
- {odxtools-6.7.0.dist-info → odxtools-7.0.0.dist-info}/entry_points.txt +0 -0
- {odxtools-6.7.0.dist-info → odxtools-7.0.0.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,13 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
-
import warnings
|
3
2
|
from dataclasses import dataclass
|
4
3
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
|
5
4
|
from xml.etree import ElementTree
|
6
5
|
|
7
|
-
from typing_extensions import override
|
6
|
+
from typing_extensions import final, override
|
8
7
|
|
9
8
|
from ..decodestate import DecodeState
|
10
9
|
from ..encodestate import EncodeState
|
11
|
-
from ..exceptions import DecodeError, EncodeError,
|
10
|
+
from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
12
11
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
13
12
|
from ..odxtypes import ParameterValue
|
14
13
|
from ..utils import dataclass_fields_asdict
|
@@ -61,15 +60,31 @@ class TableStructParameter(Parameter):
|
|
61
60
|
self._table_key = odxlinks.resolve(self.table_key_ref, TableKeyParameter)
|
62
61
|
|
63
62
|
@override
|
63
|
+
@final
|
64
64
|
def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
|
65
|
+
raise RuntimeError(f"Calling TableStructParameter._resolve_snref() is not allowed. "
|
66
|
+
f"Use ._table_struct_resolve_snrefs() instead.")
|
67
|
+
|
68
|
+
def _table_struct_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
69
|
+
param_list: List[Parameter]) -> None:
|
65
70
|
super()._resolve_snrefs(diag_layer)
|
66
71
|
|
67
72
|
if self.table_key_snref is not None:
|
68
|
-
|
69
|
-
|
70
|
-
"
|
71
|
-
|
72
|
-
|
73
|
+
tk_candidates = [p for p in param_list if p.short_name == self.table_key_snref]
|
74
|
+
if len(tk_candidates) > 1:
|
75
|
+
odxraise(f"Short name reference '{self.table_key_snref}' could "
|
76
|
+
f"not be uniquely resolved.")
|
77
|
+
elif len(tk_candidates) == 0:
|
78
|
+
odxraise(f"Short name reference '{self.table_key_snref}' could "
|
79
|
+
f"not be resolved.")
|
80
|
+
return
|
81
|
+
|
82
|
+
tk = tk_candidates[0]
|
83
|
+
if not isinstance(tk, TableKeyParameter):
|
84
|
+
odxraise(f"Table struct '{self.short_name}' references non-TableKey parameter "
|
85
|
+
f"`{self.table_key_snref}' as its table key.")
|
86
|
+
|
87
|
+
self._table_key = tk
|
73
88
|
|
74
89
|
@property
|
75
90
|
def table_key(self) -> TableKeyParameter:
|
@@ -86,71 +101,76 @@ class TableStructParameter(Parameter):
|
|
86
101
|
return True
|
87
102
|
|
88
103
|
@override
|
89
|
-
def
|
90
|
-
|
104
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
105
|
+
encode_state: EncodeState) -> None:
|
91
106
|
|
92
|
-
if not isinstance(physical_value, tuple) or \
|
107
|
+
if not isinstance(physical_value, (tuple, list)) or \
|
93
108
|
len(physical_value) != 2 or \
|
94
109
|
not isinstance(physical_value[0], str):
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
110
|
+
odxraise(
|
111
|
+
f"The physical value of TableStructParameter 'self.short_name' "
|
112
|
+
f"must be a tuple containing the short name of the selected table "
|
113
|
+
f"row as the first element and the physical value for the "
|
114
|
+
f"row's structure or DOP as the second.", EncodeError)
|
99
115
|
|
100
116
|
tr_short_name = physical_value[0]
|
101
117
|
|
102
118
|
# make sure that the same table row is selected for all
|
103
119
|
# TABLE-STRUCT parameters that are using the same key
|
104
120
|
tk_short_name = self.table_key.short_name
|
105
|
-
tk_value = encode_state.
|
121
|
+
tk_value = encode_state.table_keys.get(tk_short_name)
|
106
122
|
if tk_value is None:
|
107
123
|
# no value for the key has been set yet. Set it to the
|
108
124
|
# value which we are using right now
|
109
|
-
encode_state.
|
125
|
+
encode_state.table_keys[tk_short_name] = tr_short_name
|
110
126
|
elif tk_value != tr_short_name:
|
111
|
-
|
112
|
-
|
127
|
+
odxraise(
|
128
|
+
f"Cannot determine a unique value for table key '{tk_short_name}': "
|
129
|
+
f"Requested are '{tk_value}' and '{tr_short_name}'", EncodeError)
|
130
|
+
return
|
113
131
|
|
114
132
|
# deal with the static case (i.e., the table row is selected
|
115
133
|
# by the table key object itself)
|
116
|
-
if self.table_key.table_row is not None
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
134
|
+
if self.table_key.table_row is not None:
|
135
|
+
if tr_short_name is not None and self.table_key.table_row.short_name != tr_short_name:
|
136
|
+
odxraise(
|
137
|
+
f"The selected table row for the {self.short_name} "
|
138
|
+
f"parameter must be '{self.table_key.table_row.short_name}' "
|
139
|
+
f"instead of '{tr_short_name}'", EncodeError)
|
140
|
+
return
|
141
|
+
|
142
|
+
tr_short_name = self.table_key.table_row.short_name
|
121
143
|
|
122
144
|
# encode the user specified value using the structure (or DOP)
|
123
145
|
# of the selected table row
|
124
146
|
table = self.table_key.table
|
125
147
|
candidate_trs = [tr for tr in table.table_rows if tr.short_name == tr_short_name]
|
126
|
-
if len(candidate_trs)
|
127
|
-
|
128
|
-
|
148
|
+
if len(candidate_trs) == 0:
|
149
|
+
odxraise(
|
150
|
+
f"Could not find a table row named "
|
151
|
+
f"'{tr_short_name}' in table '{table.short_name}'", EncodeError)
|
152
|
+
return
|
153
|
+
elif len(candidate_trs) > 1:
|
154
|
+
odxraise(
|
155
|
+
f"Found multiple table rows named "
|
156
|
+
f"'{tr_short_name}' in table '{table.short_name}'", EncodeError)
|
157
|
+
|
129
158
|
tr = candidate_trs[0]
|
130
159
|
tr_value = physical_value[1]
|
131
160
|
|
132
|
-
bit_position = self.bit_position or 0
|
133
161
|
if tr.structure is not None:
|
134
162
|
# the selected table row references a structure
|
135
|
-
|
136
|
-
|
137
|
-
parameter_values=tr_value,
|
138
|
-
triggering_request=encode_state.triggering_request)
|
139
|
-
|
140
|
-
return tr.structure.convert_physical_to_bytes(
|
141
|
-
tr_value, inner_encode_state, bit_position=bit_position)
|
163
|
+
tr.structure.encode_into_pdu(tr_value, encode_state)
|
164
|
+
return
|
142
165
|
|
143
166
|
# if the table row does not reference a structure, it must
|
144
167
|
# point to a DOP!
|
145
168
|
if tr.dop is None:
|
146
|
-
odxraise(
|
169
|
+
odxraise(f"Neither a structure nor a DOP has been defined for table row"
|
170
|
+
f"'{tr.short_name}'")
|
171
|
+
return
|
147
172
|
|
148
|
-
|
149
|
-
tr_value, encode_state=encode_state, bit_position=bit_position)
|
150
|
-
|
151
|
-
@override
|
152
|
-
def encode_into_pdu(self, encode_state: EncodeState) -> bytes:
|
153
|
-
return super().encode_into_pdu(encode_state)
|
173
|
+
tr.dop.encode_into_pdu(tr_value, encode_state)
|
154
174
|
|
155
175
|
@override
|
156
176
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -7,9 +7,9 @@ from typing_extensions import override
|
|
7
7
|
|
8
8
|
from ..dataobjectproperty import DataObjectProperty
|
9
9
|
from ..encodestate import EncodeState
|
10
|
-
from ..exceptions import odxraise, odxrequire
|
10
|
+
from ..exceptions import EncodeError, odxraise, odxrequire
|
11
11
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
12
|
-
from ..odxtypes import AtomicOdxType
|
12
|
+
from ..odxtypes import AtomicOdxType, ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
14
14
|
from .parameter import ParameterType
|
15
15
|
from .parameterwithdop import ParameterWithDOP
|
@@ -77,16 +77,14 @@ class ValueParameter(ParameterWithDOP):
|
|
77
77
|
return True
|
78
78
|
|
79
79
|
@override
|
80
|
-
def
|
81
|
-
|
82
|
-
|
80
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
81
|
+
encode_state: EncodeState) -> None:
|
82
|
+
|
83
|
+
if physical_value is None:
|
84
|
+
physical_value = self._physical_default_value
|
83
85
|
if physical_value is None:
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
bit_position_int = self.bit_position if self.bit_position is not None else 0
|
91
|
-
return dop.convert_physical_to_bytes(
|
92
|
-
physical_value, encode_state=encode_state, bit_position=bit_position_int)
|
86
|
+
odxraise(
|
87
|
+
f"A value for parameter '{self.short_name}' must be specified"
|
88
|
+
f" because the parameter does not exhibit a default.", EncodeError)
|
89
|
+
|
90
|
+
self.dop.encode_into_pdu(physical_value, encode_state=encode_state)
|
odxtools/paramlengthinfotype.py
CHANGED
@@ -2,10 +2,12 @@
|
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from typing import TYPE_CHECKING, Any, Dict, cast
|
4
4
|
|
5
|
+
from typing_extensions import override
|
6
|
+
|
5
7
|
from .decodestate import DecodeState
|
6
8
|
from .diagcodedtype import DctType, DiagCodedType
|
7
9
|
from .encodestate import EncodeState
|
8
|
-
from .exceptions import odxraise
|
10
|
+
from .exceptions import EncodeError, odxraise
|
9
11
|
from .odxlink import OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
10
12
|
from .odxtypes import AtomicOdxType, DataType
|
11
13
|
|
@@ -43,35 +45,43 @@ class ParamLengthInfoType(DiagCodedType):
|
|
43
45
|
def length_key(self) -> "LengthKeyParameter":
|
44
46
|
return self._length_key
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
bit_length = encode_state.
|
48
|
+
@override
|
49
|
+
def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
|
50
|
+
bit_length = encode_state.length_keys.get(self.length_key.short_name)
|
49
51
|
|
50
52
|
if bit_length is None:
|
53
|
+
# the length key is implicit, i.e., we need to set the
|
54
|
+
# value for the length key in the encode_state based on
|
55
|
+
# the value passed here.
|
51
56
|
if self.base_data_type in [
|
52
57
|
DataType.A_BYTEFIELD,
|
53
58
|
DataType.A_ASCIISTRING,
|
54
59
|
DataType.A_UTF8STRING,
|
55
60
|
]:
|
56
|
-
bit_length = 8 * len(internal_value)
|
57
|
-
|
58
|
-
bit_length = 16 * len(internal_value)
|
59
|
-
|
60
|
-
if self.base_data_type in [DataType.A_INT32, DataType.A_UINT32]:
|
61
|
+
bit_length = 8 * len(cast(str, internal_value))
|
62
|
+
elif self.base_data_type in [DataType.A_UNICODE2STRING]:
|
63
|
+
bit_length = 16 * len(cast(str, internal_value))
|
64
|
+
elif self.base_data_type in [DataType.A_INT32, DataType.A_UINT32]:
|
61
65
|
bit_length = int(internal_value).bit_length()
|
62
66
|
if self.base_data_type == DataType.A_INT32:
|
63
67
|
bit_length += 1
|
64
68
|
# Round up
|
65
69
|
bit_length = ((bit_length + 7) // 8) * 8
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
elif self.base_data_type == DataType.A_FLOAT32:
|
71
|
+
bit_length = 32
|
72
|
+
elif self.base_data_type == DataType.A_FLOAT64:
|
73
|
+
bit_length = 64
|
74
|
+
else:
|
75
|
+
odxraise(
|
76
|
+
f"Cannot determine size of an object of type "
|
77
|
+
f"{self.base_data_type.value}", EncodeError)
|
78
|
+
return
|
79
|
+
|
80
|
+
encode_state.length_keys[self.length_key.short_name] = bit_length
|
81
|
+
|
82
|
+
encode_state.emplace_atomic_value(
|
83
|
+
internal_value=internal_value,
|
84
|
+
used_mask=None,
|
75
85
|
bit_length=bit_length,
|
76
86
|
base_data_type=self.base_data_type,
|
77
87
|
is_highlow_byte_order=self.is_highlow_byte_order,
|
@@ -82,7 +92,7 @@ class ParamLengthInfoType(DiagCodedType):
|
|
82
92
|
if self.length_key.short_name not in decode_state.length_keys:
|
83
93
|
odxraise(f"Unspecified mandatory length key parameter "
|
84
94
|
f"{self.length_key.short_name}")
|
85
|
-
decode_state.cursor_bit_position =
|
95
|
+
decode_state.cursor_bit_position = 0
|
86
96
|
return cast(None, AtomicOdxType)
|
87
97
|
|
88
98
|
bit_length = decode_state.length_keys[self.length_key.short_name]
|
@@ -91,10 +101,8 @@ class ParamLengthInfoType(DiagCodedType):
|
|
91
101
|
bit_length = 0
|
92
102
|
|
93
103
|
# Extract the internal value and return.
|
94
|
-
|
104
|
+
return decode_state.extract_atomic_value(
|
95
105
|
bit_length,
|
96
106
|
self.base_data_type,
|
97
107
|
self.is_highlow_byte_order,
|
98
108
|
)
|
99
|
-
|
100
|
-
return value
|
odxtools/request.py
CHANGED
@@ -4,7 +4,9 @@ from typing import List
|
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .basicstructure import BasicStructure
|
7
|
+
from .encodestate import EncodeState
|
7
8
|
from .odxlink import OdxDocFragment
|
9
|
+
from .odxtypes import ParameterValue
|
8
10
|
from .utils import dataclass_fields_asdict
|
9
11
|
|
10
12
|
|
@@ -20,3 +22,10 @@ class Request(BasicStructure):
|
|
20
22
|
kwargs = dataclass_fields_asdict(BasicStructure.from_et(et_element, doc_frags))
|
21
23
|
|
22
24
|
return Request(**kwargs)
|
25
|
+
|
26
|
+
def encode(self, **kwargs: ParameterValue) -> bytes:
|
27
|
+
encode_state = EncodeState(is_end_of_pdu=True)
|
28
|
+
|
29
|
+
self.encode_into_pdu(physical_value=kwargs, encode_state=encode_state)
|
30
|
+
|
31
|
+
return encode_state.coded_message
|
odxtools/response.py
CHANGED
@@ -5,10 +5,10 @@ from typing import List, Optional, cast
|
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from .basicstructure import BasicStructure
|
8
|
+
from .encodestate import EncodeState
|
8
9
|
from .exceptions import odxraise
|
9
10
|
from .odxlink import OdxDocFragment
|
10
11
|
from .odxtypes import ParameterValue
|
11
|
-
from .parameters.matchingrequestparameter import MatchingRequestParameter
|
12
12
|
from .utils import dataclass_fields_asdict
|
13
13
|
|
14
14
|
|
@@ -38,17 +38,9 @@ class Response(BasicStructure):
|
|
38
38
|
|
39
39
|
return Response(response_type=response_type, **kwargs)
|
40
40
|
|
41
|
-
def encode(self, coded_request: Optional[bytes] = None, **
|
42
|
-
|
43
|
-
# Extract MATCHING-REQUEST-PARAMs from the coded
|
44
|
-
# request. TODO: this should be done by
|
45
|
-
# MatchingRequestParam itself!
|
46
|
-
for param in self.parameters:
|
47
|
-
if isinstance(param, MatchingRequestParameter):
|
48
|
-
byte_pos = param.request_byte_position
|
49
|
-
byte_length = param.byte_length
|
41
|
+
def encode(self, coded_request: Optional[bytes] = None, **kwargs: ParameterValue) -> bytes:
|
42
|
+
encode_state = EncodeState(triggering_request=coded_request, is_end_of_pdu=True)
|
50
43
|
|
51
|
-
|
52
|
-
params[param.short_name] = val
|
44
|
+
self.encode_into_pdu(physical_value=kwargs, encode_state=encode_state)
|
53
45
|
|
54
|
-
return
|
46
|
+
return encode_state.coded_message
|
odxtools/standardlengthtype.py
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Literal, Optional
|
4
|
+
|
5
|
+
from typing_extensions import override
|
4
6
|
|
5
7
|
from .decodestate import DecodeState
|
6
8
|
from .diagcodedtype import DctType, DiagCodedType
|
7
9
|
from .encodestate import EncodeState
|
8
|
-
from .exceptions import odxassert, odxraise
|
10
|
+
from .exceptions import odxassert, odxraise, odxrequire
|
9
11
|
from .odxtypes import AtomicOdxType, DataType
|
10
12
|
|
11
13
|
|
@@ -20,6 +22,10 @@ class StandardLengthType(DiagCodedType):
|
|
20
22
|
def dct_type(self) -> DctType:
|
21
23
|
return "STANDARD-LENGTH-TYPE"
|
22
24
|
|
25
|
+
@property
|
26
|
+
def is_condensed(self) -> bool:
|
27
|
+
return self.is_condensed_raw is True
|
28
|
+
|
23
29
|
def __post_init__(self) -> None:
|
24
30
|
if self.bit_mask is not None:
|
25
31
|
maskable_types = (DataType.A_UINT32, DataType.A_INT32, DataType.A_BYTEFIELD)
|
@@ -28,11 +34,43 @@ class StandardLengthType(DiagCodedType):
|
|
28
34
|
'Can not apply a bit_mask on a value of type {self.base_data_type}',
|
29
35
|
)
|
30
36
|
|
37
|
+
def __get_raw_mask(self, internal_value: AtomicOdxType) -> Optional[bytes]:
|
38
|
+
"""Returns a byte field where all bits that are used by the
|
39
|
+
DiagCoded type are set and all unused ones are not set.
|
40
|
+
|
41
|
+
If `None` is returned, all bits are used.
|
42
|
+
"""
|
43
|
+
if self.bit_mask is None:
|
44
|
+
return None
|
45
|
+
|
46
|
+
if self.is_condensed:
|
47
|
+
odxraise("Condensed bit masks are not yet supported", NotImplementedError)
|
48
|
+
return
|
49
|
+
|
50
|
+
endianness: Literal["little", "big"] = "big"
|
51
|
+
if not self.is_highlow_byte_order and self.base_data_type in [
|
52
|
+
DataType.A_INT32, DataType.A_UINT32, DataType.A_FLOAT32, DataType.A_FLOAT64
|
53
|
+
]:
|
54
|
+
# TODO (?): Technically, little endian A_UNICODE2STRING
|
55
|
+
# objects require a byte swap for each 16 bit letter, and
|
56
|
+
# thus also for the mask. I somehow doubt that this has
|
57
|
+
# been anticipated by the standard, though...
|
58
|
+
endianness = "little"
|
59
|
+
|
60
|
+
sz: int
|
61
|
+
if isinstance(internal_value, (bytes, bytearray)):
|
62
|
+
sz = len(internal_value)
|
63
|
+
else:
|
64
|
+
sz = (odxrequire(self.get_static_bit_length()) + 7) // 8
|
65
|
+
|
66
|
+
return self.bit_mask.to_bytes(sz, endianness)
|
67
|
+
|
31
68
|
def __apply_mask(self, internal_value: AtomicOdxType) -> AtomicOdxType:
|
32
69
|
if self.bit_mask is None:
|
33
70
|
return internal_value
|
34
|
-
if self.
|
35
|
-
|
71
|
+
if self.is_condensed:
|
72
|
+
odxraise("Serialization of condensed bit mask is not supported", NotImplementedError)
|
73
|
+
return
|
36
74
|
if isinstance(internal_value, int):
|
37
75
|
return internal_value & self.bit_mask
|
38
76
|
if isinstance(internal_value, bytes):
|
@@ -46,16 +84,16 @@ class StandardLengthType(DiagCodedType):
|
|
46
84
|
def get_static_bit_length(self) -> Optional[int]:
|
47
85
|
return self.bit_length
|
48
86
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
self.__apply_mask(internal_value),
|
53
|
-
|
54
|
-
self.bit_length,
|
55
|
-
self.base_data_type,
|
56
|
-
is_highlow_byte_order=self.is_highlow_byte_order
|
57
|
-
)
|
87
|
+
@override
|
88
|
+
def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
|
89
|
+
encode_state.emplace_atomic_value(
|
90
|
+
internal_value=self.__apply_mask(internal_value),
|
91
|
+
used_mask=self.__get_raw_mask(internal_value),
|
92
|
+
bit_length=self.bit_length,
|
93
|
+
base_data_type=self.base_data_type,
|
94
|
+
is_highlow_byte_order=self.is_highlow_byte_order)
|
58
95
|
|
96
|
+
@override
|
59
97
|
def decode_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
|
60
98
|
internal_value = decode_state.extract_atomic_value(
|
61
99
|
self.bit_length,
|
odxtools/staticfield.py
CHANGED
@@ -48,36 +48,32 @@ class StaticField(Field):
|
|
48
48
|
super()._resolve_snrefs(diag_layer)
|
49
49
|
|
50
50
|
@override
|
51
|
-
def
|
52
|
-
|
53
|
-
physical_value: ParameterValue,
|
54
|
-
encode_state: EncodeState,
|
55
|
-
bit_position: int = 0,
|
56
|
-
) -> bytes:
|
51
|
+
def encode_into_pdu(self, physical_value: ParameterValue, encode_state: EncodeState) -> None:
|
52
|
+
|
57
53
|
if not isinstance(physical_value,
|
58
54
|
(tuple, list)) or len(physical_value) != self.fixed_number_of_items:
|
59
55
|
odxraise(f"Value for static field '{self.short_name}' "
|
60
56
|
f"must be a list of size {self.fixed_number_of_items}")
|
61
57
|
|
62
|
-
result = bytearray()
|
63
58
|
for val in physical_value:
|
64
59
|
if not isinstance(val, dict):
|
65
60
|
odxraise(f"The individual parameter values for static field '{self.short_name}' "
|
66
61
|
f"must be dictionaries for structure '{self.structure.short_name}'")
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
pos_before = encode_state.cursor_byte_position
|
64
|
+
self.structure.encode_into_pdu(val, encode_state)
|
65
|
+
pos_after = encode_state.cursor_byte_position
|
66
|
+
|
67
|
+
if pos_after - pos_before > self.item_byte_size:
|
68
|
+
odxraise(
|
69
|
+
f"Insufficient item byte size for static field {self.short_name}: "
|
70
|
+
f"Is {self.item_byte_size} bytes, but need at least {pos_after - pos_before} bytes"
|
71
|
+
)
|
72
|
+
encode_state.cursor_byte_position = pos_before + self.item_byte_size
|
73
|
+
elif pos_after - pos_before < self.item_byte_size:
|
75
74
|
# add some padding bytes
|
76
|
-
|
77
|
-
|
78
|
-
result += data
|
79
|
-
|
80
|
-
return result
|
75
|
+
encode_state.emplace_bytes(b'\x00' * (self.item_byte_size -
|
76
|
+
(pos_after - pos_before)))
|
81
77
|
|
82
78
|
@override
|
83
79
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
odxtools/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: odxtools
|
3
|
-
Version:
|
3
|
+
Version: 7.0.0
|
4
4
|
Summary: Utilities to work with the ODX standard for automotive diagnostics
|
5
5
|
Author-email: Katrin Bauer <katrin.bauer@mbition.io>, Andreas Lauser <andreas.lauser@mbition.io>, Ayoub Kaanich <kayoub5@live.com>
|
6
6
|
Maintainer-email: Andreas Lauser <andreas.lauser@mbition.io>, Ayoub Kaanich <kayoub5@live.com>
|