odxtools 6.7.1__py3-none-any.whl → 7.1.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 +102 -112
- odxtools/dataobjectproperty.py +3 -7
- odxtools/decodestate.py +1 -13
- odxtools/diagcodedtype.py +9 -96
- odxtools/diagcomm.py +11 -3
- odxtools/diagdatadictionaryspec.py +14 -14
- odxtools/diaglayer.py +52 -1
- odxtools/diaglayerraw.py +13 -7
- odxtools/diagservice.py +12 -16
- odxtools/dopbase.py +5 -8
- odxtools/dtcdop.py +21 -19
- odxtools/dynamicendmarkerfield.py +119 -0
- odxtools/dynamiclengthfield.py +39 -29
- odxtools/dynenddopref.py +38 -0
- odxtools/encodestate.py +188 -23
- odxtools/endofpdufield.py +33 -18
- odxtools/environmentdata.py +8 -1
- odxtools/environmentdatadescription.py +21 -15
- odxtools/field.py +4 -3
- odxtools/leadinglengthinfotype.py +25 -12
- odxtools/matchingparameter.py +2 -2
- odxtools/minmaxlengthtype.py +36 -26
- odxtools/multiplexer.py +42 -23
- odxtools/multiplexercase.py +3 -3
- odxtools/multiplexerdefaultcase.py +7 -3
- odxtools/nameditemlist.py +14 -0
- odxtools/odxlink.py +38 -4
- odxtools/odxtypes.py +20 -2
- odxtools/parameterinfo.py +126 -40
- odxtools/parameters/codedconstparameter.py +17 -13
- odxtools/parameters/dynamicparameter.py +5 -4
- odxtools/parameters/lengthkeyparameter.py +66 -17
- odxtools/parameters/matchingrequestparameter.py +23 -11
- odxtools/parameters/nrcconstparameter.py +42 -22
- odxtools/parameters/parameter.py +35 -42
- odxtools/parameters/parameterwithdop.py +15 -22
- odxtools/parameters/physicalconstantparameter.py +16 -16
- odxtools/parameters/reservedparameter.py +5 -2
- odxtools/parameters/systemparameter.py +3 -2
- odxtools/parameters/tableentryparameter.py +3 -2
- odxtools/parameters/tablekeyparameter.py +88 -39
- odxtools/parameters/tablestructparameter.py +45 -44
- odxtools/parameters/valueparameter.py +16 -17
- odxtools/paramlengthinfotype.py +30 -22
- odxtools/request.py +9 -0
- odxtools/response.py +5 -13
- odxtools/standardlengthtype.py +51 -13
- odxtools/statechart.py +5 -9
- odxtools/statetransition.py +3 -8
- odxtools/staticfield.py +30 -20
- odxtools/tablerow.py +5 -3
- odxtools/templates/macros/printDynamicEndmarkerField.xml.jinja2 +16 -0
- odxtools/templates/macros/printVariant.xml.jinja2 +8 -0
- odxtools/version.py +2 -2
- {odxtools-6.7.1.dist-info → odxtools-7.1.0.dist-info}/METADATA +1 -1
- {odxtools-6.7.1.dist-info → odxtools-7.1.0.dist-info}/RECORD +60 -57
- {odxtools-6.7.1.dist-info → odxtools-7.1.0.dist-info}/LICENSE +0 -0
- {odxtools-6.7.1.dist-info → odxtools-7.1.0.dist-info}/WHEEL +0 -0
- {odxtools-6.7.1.dist-info → odxtools-7.1.0.dist-info}/entry_points.txt +0 -0
- {odxtools-6.7.1.dist-info → odxtools-7.1.0.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,17 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, Any, Dict, List
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
|
-
from typing_extensions import override
|
6
|
+
from typing_extensions import final, override
|
7
7
|
|
8
8
|
from ..decodestate import DecodeState
|
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
12
|
from ..odxtypes import ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
14
|
-
from .parameter import ParameterType
|
14
|
+
from .parameter import Parameter, ParameterType
|
15
15
|
from .parameterwithdop import ParameterWithDOP
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
@@ -60,8 +60,9 @@ class LengthKeyParameter(ParameterWithDOP):
|
|
60
60
|
super()._resolve_odxlinks(odxlinks)
|
61
61
|
|
62
62
|
@override
|
63
|
-
def
|
64
|
-
|
63
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
64
|
+
param_list: List[Parameter]) -> None:
|
65
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
65
66
|
|
66
67
|
@property
|
67
68
|
@override
|
@@ -77,17 +78,65 @@ class LengthKeyParameter(ParameterWithDOP):
|
|
77
78
|
return True
|
78
79
|
|
79
80
|
@override
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
def
|
90
|
-
|
81
|
+
@final
|
82
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
83
|
+
encode_state: EncodeState) -> None:
|
84
|
+
# if you get this exception, you ought to use
|
85
|
+
# `.encode_placeholder_into_pdu()` followed by (after the
|
86
|
+
# value of the length key has been determined)
|
87
|
+
# `.encode_value_into_pdu()`.
|
88
|
+
raise RuntimeError("_encode_positioned_into_pdu() cannot be called for length keys.")
|
89
|
+
|
90
|
+
def encode_placeholder_into_pdu(self, physical_value: Optional[ParameterValue],
|
91
|
+
encode_state: EncodeState) -> None:
|
92
|
+
|
93
|
+
if physical_value is not None:
|
94
|
+
if not self.dop.is_valid_physical_value(physical_value):
|
95
|
+
odxraise(f"Invalid explicitly specified physical value '{physical_value!r}' "
|
96
|
+
f"for length key '{self.short_name}'.")
|
97
|
+
|
98
|
+
lkv = encode_state.length_keys.get(self.short_name)
|
99
|
+
if lkv is not None and lkv != physical_value:
|
100
|
+
odxraise(f"Got conflicting values for length key {self.short_name}: "
|
101
|
+
f"{lkv} and {physical_value!r}")
|
102
|
+
|
103
|
+
if not isinstance(physical_value, int):
|
104
|
+
odxraise(
|
105
|
+
f"Value of length key {self.short_name} is of type {type(physical_value).__name__} "
|
106
|
+
f"instead of int")
|
107
|
+
|
108
|
+
encode_state.length_keys[self.short_name] = physical_value
|
109
|
+
|
110
|
+
orig_cursor = encode_state.cursor_byte_position
|
111
|
+
pos = encode_state.cursor_byte_position
|
112
|
+
if self.byte_position is not None:
|
113
|
+
pos = encode_state.origin_byte_position + self.byte_position
|
114
|
+
encode_state.key_pos[self.short_name] = pos
|
115
|
+
encode_state.cursor_byte_position = pos
|
116
|
+
encode_state.cursor_bit_position = self.bit_position or 0
|
117
|
+
|
118
|
+
# emplace a value of zero into the encode state, but pretend the bits not to be used
|
119
|
+
n = odxrequire(self.dop.get_static_bit_length()) + encode_state.cursor_bit_position
|
120
|
+
tmp_val = b'\x00' * ((n + 7) // 8)
|
121
|
+
encode_state.emplace_bytes(tmp_val, obj_used_mask=tmp_val)
|
122
|
+
|
123
|
+
encode_state.cursor_byte_position = max(encode_state.cursor_byte_position, orig_cursor)
|
124
|
+
encode_state.cursor_bit_position = 0
|
125
|
+
|
126
|
+
def encode_value_into_pdu(self, encode_state: EncodeState) -> None:
|
127
|
+
|
128
|
+
if self.short_name not in encode_state.length_keys:
|
129
|
+
odxraise(
|
130
|
+
f"Length key {self.short_name} has not been defined before "
|
131
|
+
f"it is required.", EncodeError)
|
132
|
+
return
|
133
|
+
else:
|
134
|
+
physical_value = encode_state.length_keys[self.short_name]
|
135
|
+
|
136
|
+
encode_state.cursor_byte_position = encode_state.key_pos[self.short_name]
|
137
|
+
encode_state.cursor_bit_position = self.bit_position or 0
|
138
|
+
|
139
|
+
self.dop.encode_into_pdu(encode_state=encode_state, physical_value=physical_value)
|
91
140
|
|
92
141
|
@override
|
93
142
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -7,7 +7,7 @@ from typing_extensions import override
|
|
7
7
|
|
8
8
|
from ..decodestate import DecodeState
|
9
9
|
from ..encodestate import EncodeState
|
10
|
-
from ..exceptions import EncodeError, odxrequire
|
10
|
+
from ..exceptions import EncodeError, odxraise, odxrequire
|
11
11
|
from ..odxlink import OdxDocFragment
|
12
12
|
from ..odxtypes import DataType, ParameterValue
|
13
13
|
from ..utils import dataclass_fields_asdict
|
@@ -52,19 +52,31 @@ class MatchingRequestParameter(Parameter):
|
|
52
52
|
return False
|
53
53
|
|
54
54
|
@override
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
56
|
+
encode_state: EncodeState) -> None:
|
57
|
+
if encode_state.triggering_request is None:
|
58
|
+
odxraise(
|
59
|
+
f"Parameter '{self.short_name}' is of matching request type,"
|
60
|
+
f" but no original request has been specified.", EncodeError)
|
61
|
+
return
|
62
|
+
|
63
|
+
rq_pos = self.request_byte_position
|
64
|
+
rq_len = self.byte_length
|
65
|
+
|
66
|
+
if len(encode_state.triggering_request) < rq_pos + rq_len:
|
67
|
+
odxraise(
|
68
|
+
f"Specified triggering request 0x{encode_state.triggering_request.hex()} "
|
69
|
+
f"is not long enough to encode matching request parameter "
|
70
|
+
f"'{self.short_name}': Have {len(encode_state.triggering_request)} "
|
71
|
+
f"bytes, need at least {rq_pos + rq_len} bytes", EncodeError)
|
72
|
+
return
|
73
|
+
|
74
|
+
encode_state.emplace_bytes(encode_state.triggering_request[rq_pos:rq_pos + rq_len],
|
75
|
+
self.short_name)
|
62
76
|
|
63
77
|
@override
|
64
78
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
65
|
-
|
79
|
+
return decode_state.extract_atomic_value(
|
66
80
|
bit_length=self.byte_length * 8,
|
67
81
|
base_data_type=DataType.A_UINT32,
|
68
82
|
is_highlow_byte_order=False)
|
69
|
-
|
70
|
-
return result
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
import warnings
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
|
5
5
|
from xml.etree import ElementTree
|
6
6
|
|
7
7
|
from typing_extensions import override
|
@@ -10,9 +10,9 @@ from ..createanydiagcodedtype import create_any_diag_coded_type_from_et
|
|
10
10
|
from ..decodestate import DecodeState
|
11
11
|
from ..diagcodedtype import DiagCodedType
|
12
12
|
from ..encodestate import EncodeState
|
13
|
-
from ..exceptions import DecodeError, EncodeError, odxrequire
|
13
|
+
from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
14
14
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
15
|
-
from ..odxtypes import AtomicOdxType, DataType
|
15
|
+
from ..odxtypes import AtomicOdxType, DataType, ParameterValue
|
16
16
|
from ..utils import dataclass_fields_asdict
|
17
17
|
from .parameter import Parameter, ParameterType
|
18
18
|
|
@@ -22,13 +22,19 @@ if TYPE_CHECKING:
|
|
22
22
|
|
23
23
|
@dataclass
|
24
24
|
class NrcConstParameter(Parameter):
|
25
|
-
"""A param of type NRC-CONST defines a set of values to be matched.
|
25
|
+
"""A param of type NRC-CONST defines a set of values to be matched for a negative response to apply.
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
The behaviour of NRC-CONST parameters is similar to CODED-CONST
|
28
|
+
parameters in that they allow to specify which coding objects
|
29
|
+
apply to a binary string, but in contrast to CODED-CONST
|
30
|
+
parameters they allow to specify multiple values. Thus, the value
|
31
|
+
of a CODED-CONST parameter is usually set using an overlapping
|
32
|
+
VALUE parameter. Since NRC-CONST parameters can only be specified
|
33
|
+
for negative responses, they can thus be regarded as a multiplexer
|
34
|
+
mechanism that is specific to negative responses.
|
30
35
|
|
31
36
|
See ASAM MCD-2 D (ODX), p. 77-79.
|
37
|
+
|
32
38
|
"""
|
33
39
|
|
34
40
|
diag_coded_type: DiagCodedType
|
@@ -69,8 +75,9 @@ class NrcConstParameter(Parameter):
|
|
69
75
|
super()._resolve_odxlinks(odxlinks)
|
70
76
|
|
71
77
|
@override
|
72
|
-
def
|
73
|
-
|
78
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
79
|
+
param_list: List[Parameter]) -> None:
|
80
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
74
81
|
|
75
82
|
@override
|
76
83
|
def get_static_bit_length(self) -> Optional[int]:
|
@@ -91,21 +98,34 @@ class NrcConstParameter(Parameter):
|
|
91
98
|
return False
|
92
99
|
|
93
100
|
@override
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
101
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
102
|
+
encode_state: EncodeState) -> None:
|
103
|
+
coded_value: ParameterValue
|
104
|
+
if physical_value is not None:
|
105
|
+
if physical_value not in self.coded_values:
|
106
|
+
odxraise(
|
107
|
+
f"The value of parameter '{self.short_name}' must "
|
108
|
+
f" be one of {self.coded_values} (is: {physical_value!r})", EncodeError)
|
109
|
+
coded_value = self.coded_values[0]
|
99
110
|
else:
|
100
|
-
coded_value =
|
111
|
+
coded_value = physical_value
|
101
112
|
else:
|
102
|
-
# If the user
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
113
|
+
# If the user did not select a value, the value of the
|
114
|
+
# this parameter is set by another parameter which
|
115
|
+
# overlaps with it. We thus just move the cursor.
|
116
|
+
bit_pos = encode_state.cursor_bit_position
|
117
|
+
bit_len = self.diag_coded_type.get_static_bit_length()
|
118
|
+
|
119
|
+
if bit_len is None:
|
120
|
+
odxraise("The diag coded type of NRC-CONST parameters must "
|
121
|
+
"exhibit a static size")
|
122
|
+
return
|
123
|
+
|
124
|
+
encode_state.cursor_byte_position += (bit_pos + bit_len + 7) // 8
|
125
|
+
encode_state.cursor_bit_position = 0
|
126
|
+
return
|
127
|
+
|
128
|
+
self.diag_coded_type.encode_into_pdu(cast(AtomicOdxType, coded_value), encode_state)
|
109
129
|
|
110
130
|
@override
|
111
131
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> AtomicOdxType:
|
odxtools/parameters/parameter.py
CHANGED
@@ -82,7 +82,13 @@ class Parameter(NamedElement):
|
|
82
82
|
for sdg in self.sdgs:
|
83
83
|
sdg._resolve_odxlinks(odxlinks)
|
84
84
|
|
85
|
+
@final
|
85
86
|
def _resolve_snrefs(self, diag_layer: "DiagLayer") -> None:
|
87
|
+
raise RuntimeError("Calling _resolve_snrefs() is not allowed for parameters. "
|
88
|
+
"Use _parameter_resolve_snrefs() instead.")
|
89
|
+
|
90
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
91
|
+
param_list: List["Parameter"]) -> None:
|
86
92
|
for sdg in self.sdgs:
|
87
93
|
sdg._resolve_snrefs(diag_layer)
|
88
94
|
|
@@ -117,12 +123,35 @@ class Parameter(NamedElement):
|
|
117
123
|
"""
|
118
124
|
raise NotImplementedError(".is_settable is not implemented by the concrete parameter class")
|
119
125
|
|
120
|
-
|
121
|
-
|
122
|
-
|
126
|
+
@final
|
127
|
+
def encode_into_pdu(self, physical_value: Optional[ParameterValue],
|
128
|
+
encode_state: EncodeState) -> None:
|
129
|
+
"""Convert a physical value into its encoded form and place it into the PDU
|
130
|
+
|
131
|
+
Also, adapt the `encode_state` so that it points to where the next
|
132
|
+
parameter is located (if the parameter does not explicitly specify a
|
133
|
+
position)
|
123
134
|
"""
|
135
|
+
|
136
|
+
orig_cursor = encode_state.cursor_byte_position
|
137
|
+
if self.byte_position is not None:
|
138
|
+
encode_state.cursor_byte_position = encode_state.origin_byte_position + self.byte_position
|
139
|
+
|
140
|
+
encode_state.cursor_bit_position = self.bit_position or 0
|
141
|
+
|
142
|
+
self._encode_positioned_into_pdu(physical_value, encode_state)
|
143
|
+
|
144
|
+
encode_state.cursor_byte_position = max(encode_state.cursor_byte_position, orig_cursor)
|
145
|
+
encode_state.cursor_bit_position = 0
|
146
|
+
|
147
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
148
|
+
encode_state: EncodeState) -> None:
|
149
|
+
"""Method which actually encodes the parameter
|
150
|
+
|
151
|
+
Its location is managed by `Parameter`."""
|
124
152
|
raise NotImplementedError(
|
125
|
-
"
|
153
|
+
f"Required method '_encode_positioned_into_pdu()' not implemented by "
|
154
|
+
f"child class {type(self).__name__}")
|
126
155
|
|
127
156
|
@final
|
128
157
|
def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -144,41 +173,5 @@ class Parameter(NamedElement):
|
|
144
173
|
|
145
174
|
Its location is managed by `Parameter`."""
|
146
175
|
raise NotImplementedError(
|
147
|
-
"Required method '_decode_positioned_from_pdu()' not implemented by
|
148
|
-
|
149
|
-
def encode_into_pdu(self, encode_state: EncodeState) -> bytes:
|
150
|
-
"""Encode the value of a parameter into a binary blob and return it
|
151
|
-
|
152
|
-
If the byte position of the parameter is not defined,
|
153
|
-
the byte code is appended to the blob.
|
154
|
-
|
155
|
-
Technical note for subclasses: The default implementation
|
156
|
-
tries to compute the coded value via
|
157
|
-
`self.get_coded_value_as_bytes(encoded_state)` and inserts it
|
158
|
-
into the PDU. Thus it usually suffices to overwrite
|
159
|
-
`get_coded_value_as_bytes()` instead of `encode_into_pdu()`.
|
160
|
-
|
161
|
-
Parameters:
|
162
|
-
----------
|
163
|
-
encode_state: EncodeState, i.e. a named tuple with attributes
|
164
|
-
* coded_message: bytes, the message encoded so far
|
165
|
-
* parameter_values: List[ParameterValuePairs]
|
166
|
-
* triggering_coded_request: bytes
|
167
|
-
|
168
|
-
Returns:
|
169
|
-
-------
|
170
|
-
bytes
|
171
|
-
the message's blob after adding the encoded parameter into it
|
172
|
-
|
173
|
-
"""
|
174
|
-
msg_blob = encode_state.coded_message
|
175
|
-
param_blob = self.get_coded_value_as_bytes(encode_state)
|
176
|
-
|
177
|
-
if self.byte_position is not None:
|
178
|
-
byte_position = self.byte_position
|
179
|
-
else:
|
180
|
-
byte_position = len(msg_blob)
|
181
|
-
|
182
|
-
encode_state.emplace_atomic_value(param_blob, self.short_name, byte_position)
|
183
|
-
|
184
|
-
return encode_state.coded_message
|
176
|
+
f"Required method '_decode_positioned_from_pdu()' not implemented by "
|
177
|
+
f"child class {type(self).__name__}")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -11,8 +11,8 @@ from ..dopbase import DopBase
|
|
11
11
|
from ..dtcdop import DtcDop
|
12
12
|
from ..encodestate import EncodeState
|
13
13
|
from ..exceptions import odxassert, odxrequire
|
14
|
-
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
15
|
-
from ..odxtypes import ParameterValue
|
14
|
+
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
|
15
|
+
from ..odxtypes import AtomicOdxType, ParameterValue
|
16
16
|
from ..physicaltype import PhysicalType
|
17
17
|
from ..utils import dataclass_fields_asdict
|
18
18
|
from .parameter import Parameter
|
@@ -43,7 +43,7 @@ class ParameterWithDOP(Parameter):
|
|
43
43
|
def __post_init__(self) -> None:
|
44
44
|
odxassert(self.dop_snref is not None or self.dop_ref is not None,
|
45
45
|
f"Param {self.short_name} without a DOP-(SN)REF should not exist!")
|
46
|
-
self._dop:
|
46
|
+
self._dop: DopBase
|
47
47
|
|
48
48
|
@override
|
49
49
|
def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
|
@@ -55,26 +55,22 @@ class ParameterWithDOP(Parameter):
|
|
55
55
|
|
56
56
|
if self.dop_ref is not None:
|
57
57
|
odxassert(self.dop_snref is None)
|
58
|
-
|
59
|
-
# that currently not all kinds of DOPs are internalized
|
60
|
-
# (e.g., static and dynamic fields)
|
61
|
-
self._dop = odxlinks.resolve_lenient(self.dop_ref)
|
58
|
+
self._dop = odxlinks.resolve(self.dop_ref)
|
62
59
|
|
63
60
|
@override
|
64
|
-
def
|
65
|
-
|
61
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
62
|
+
param_list: List[Parameter]) -> None:
|
63
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
66
64
|
|
67
65
|
if self.dop_snref:
|
68
|
-
|
69
|
-
self._dop =
|
66
|
+
all_dops = diag_layer.diag_data_dictionary_spec.all_data_object_properties
|
67
|
+
self._dop = resolve_snref(self.dop_snref, all_dops, DopBase)
|
70
68
|
|
71
69
|
@property
|
72
70
|
def dop(self) -> DopBase:
|
73
|
-
"""
|
71
|
+
"""This is usually a DataObjectProperty or a Structure object"""
|
74
72
|
|
75
|
-
return
|
76
|
-
self._dop, "Specifying a data object property is mandatory but it "
|
77
|
-
"could not be resolved")
|
73
|
+
return self._dop
|
78
74
|
|
79
75
|
@override
|
80
76
|
def get_static_bit_length(self) -> Optional[int]:
|
@@ -91,12 +87,9 @@ class ParameterWithDOP(Parameter):
|
|
91
87
|
return None
|
92
88
|
|
93
89
|
@override
|
94
|
-
def
|
95
|
-
|
96
|
-
physical_value
|
97
|
-
bit_position_int = self.bit_position if self.bit_position is not None else 0
|
98
|
-
return dop.convert_physical_to_bytes(
|
99
|
-
physical_value, encode_state, bit_position=bit_position_int)
|
90
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
91
|
+
encode_state: EncodeState) -> None:
|
92
|
+
self.dop.encode_into_pdu(cast(AtomicOdxType, physical_value), encode_state)
|
100
93
|
|
101
94
|
@override
|
102
95
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, Any, Dict, List
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -8,11 +8,11 @@ from typing_extensions import override
|
|
8
8
|
from ..dataobjectproperty import DataObjectProperty
|
9
9
|
from ..decodestate import DecodeState
|
10
10
|
from ..encodestate import EncodeState
|
11
|
-
from ..exceptions import DecodeError, odxraise, odxrequire
|
11
|
+
from ..exceptions import DecodeError, EncodeError, odxraise, odxrequire
|
12
12
|
from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
|
13
13
|
from ..odxtypes import ParameterValue
|
14
14
|
from ..utils import dataclass_fields_asdict
|
15
|
-
from .parameter import ParameterType
|
15
|
+
from .parameter import Parameter, ParameterType
|
16
16
|
from .parameterwithdop import ParameterWithDOP
|
17
17
|
|
18
18
|
if TYPE_CHECKING:
|
@@ -50,8 +50,9 @@ class PhysicalConstantParameter(ParameterWithDOP):
|
|
50
50
|
super()._resolve_odxlinks(odxlinks)
|
51
51
|
|
52
52
|
@override
|
53
|
-
def
|
54
|
-
|
53
|
+
def _parameter_resolve_snrefs(self, diag_layer: "DiagLayer", *,
|
54
|
+
param_list: List[Parameter]) -> None:
|
55
|
+
super()._parameter_resolve_snrefs(diag_layer, param_list=param_list)
|
55
56
|
|
56
57
|
dop = odxrequire(self.dop)
|
57
58
|
if not isinstance(dop, DataObjectProperty):
|
@@ -74,17 +75,15 @@ class PhysicalConstantParameter(ParameterWithDOP):
|
|
74
75
|
return False
|
75
76
|
|
76
77
|
@override
|
77
|
-
def
|
78
|
-
|
79
|
-
if
|
80
|
-
|
81
|
-
|
82
|
-
f"
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
return dop.convert_physical_to_bytes(
|
87
|
-
self.physical_constant_value, encode_state, bit_position=bit_position_int)
|
78
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
79
|
+
encode_state: EncodeState) -> None:
|
80
|
+
if physical_value is not None and physical_value != self.physical_constant_value:
|
81
|
+
odxraise(
|
82
|
+
f"Value for constant parameter `{self.short_name}` name can "
|
83
|
+
f"only be specified as {self.physical_constant_value!r} (is: {physical_value!r})",
|
84
|
+
EncodeError)
|
85
|
+
|
86
|
+
self.dop.encode_into_pdu(self.physical_constant_value, encode_state)
|
88
87
|
|
89
88
|
@override
|
90
89
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -99,4 +98,5 @@ class PhysicalConstantParameter(ParameterWithDOP):
|
|
99
98
|
f"{self.physical_constant_value!r} but got {phys_val!r} "
|
100
99
|
f"at byte position {decode_state.cursor_byte_position} "
|
101
100
|
f"in coded message {decode_state.coded_message.hex()}.", DecodeError)
|
101
|
+
|
102
102
|
return phys_val
|
@@ -49,8 +49,11 @@ class ReservedParameter(Parameter):
|
|
49
49
|
return self.bit_length
|
50
50
|
|
51
51
|
@override
|
52
|
-
def
|
53
|
-
|
52
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
53
|
+
encode_state: EncodeState) -> None:
|
54
|
+
raw_data = (0).to_bytes((encode_state.cursor_bit_position + self.bit_length + 7) // 8,
|
55
|
+
"big")
|
56
|
+
encode_state.emplace_bytes(raw_data, self.short_name)
|
54
57
|
|
55
58
|
@override
|
56
59
|
def _decode_positioned_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import List
|
3
|
+
from typing import List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -46,7 +46,8 @@ class SystemParameter(ParameterWithDOP):
|
|
46
46
|
raise NotImplementedError("SystemParameter.is_settable is not implemented yet.")
|
47
47
|
|
48
48
|
@override
|
49
|
-
def
|
49
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
50
|
+
encode_state: EncodeState) -> None:
|
50
51
|
raise NotImplementedError("Encoding a SystemParameter is not implemented yet.")
|
51
52
|
|
52
53
|
@override
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING, List
|
3
|
+
from typing import TYPE_CHECKING, List, Optional
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from typing_extensions import override
|
@@ -59,7 +59,8 @@ class TableEntryParameter(Parameter):
|
|
59
59
|
raise NotImplementedError("TableEntryParameter.is_settable is not implemented yet.")
|
60
60
|
|
61
61
|
@override
|
62
|
-
def
|
62
|
+
def _encode_positioned_into_pdu(self, physical_value: Optional[ParameterValue],
|
63
|
+
encode_state: EncodeState) -> None:
|
63
64
|
raise NotImplementedError("Encoding a TableEntryParameter is not implemented yet.")
|
64
65
|
|
65
66
|
@property
|