odxtools 5.3.1__py3-none-any.whl → 6.0.1__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/__init__.py +1 -1
- odxtools/basicstructure.py +76 -91
- odxtools/cli/_parser_utils.py +12 -9
- odxtools/cli/_print_utils.py +7 -7
- odxtools/cli/browse.py +94 -73
- odxtools/cli/find.py +42 -59
- odxtools/cli/list.py +21 -17
- odxtools/cli/snoop.py +19 -18
- odxtools/communicationparameterref.py +6 -3
- odxtools/companydocinfo.py +2 -2
- odxtools/companyrevisioninfo.py +1 -1
- odxtools/comparamsubset.py +6 -6
- odxtools/complexcomparam.py +1 -1
- odxtools/compumethods/compumethod.py +6 -9
- odxtools/compumethods/createanycompumethod.py +11 -9
- odxtools/compumethods/identicalcompumethod.py +5 -4
- odxtools/compumethods/limit.py +9 -9
- odxtools/compumethods/linearcompumethod.py +25 -17
- odxtools/compumethods/scalelinearcompumethod.py +6 -5
- odxtools/compumethods/tabintpcompumethod.py +30 -9
- odxtools/compumethods/texttablecompumethod.py +22 -24
- odxtools/database.py +5 -5
- odxtools/dataobjectproperty.py +10 -23
- odxtools/decodestate.py +1 -1
- odxtools/determinenumberofitems.py +37 -8
- odxtools/diagcodedtype.py +14 -9
- odxtools/diagdatadictionaryspec.py +60 -37
- odxtools/diaglayer.py +30 -21
- odxtools/diaglayercontainer.py +40 -40
- odxtools/diaglayerraw.py +92 -63
- odxtools/diagnostictroublecode.py +2 -2
- odxtools/diagservice.py +53 -35
- odxtools/docrevision.py +1 -1
- odxtools/dopbase.py +14 -3
- odxtools/dtcdop.py +15 -9
- odxtools/dynamiclengthfield.py +6 -4
- odxtools/endofpdufield.py +22 -23
- odxtools/environmentdata.py +2 -5
- odxtools/environmentdatadescription.py +6 -4
- odxtools/field.py +3 -8
- odxtools/isotp_state_machine.py +52 -38
- odxtools/leadinglengthinfotype.py +9 -7
- odxtools/load_file.py +2 -1
- odxtools/load_odx_d_file.py +2 -5
- odxtools/load_pdx_file.py +2 -6
- odxtools/message.py +11 -3
- odxtools/minmaxlengthtype.py +107 -78
- odxtools/modification.py +2 -2
- odxtools/multiplexer.py +23 -21
- odxtools/multiplexerswitchkey.py +37 -8
- odxtools/nameditemlist.py +59 -58
- odxtools/odxlink.py +4 -2
- odxtools/odxtypes.py +4 -3
- odxtools/parameterinfo.py +6 -6
- odxtools/parameters/codedconstparameter.py +15 -25
- odxtools/parameters/createanyparameter.py +1 -1
- odxtools/parameters/dynamicparameter.py +6 -5
- odxtools/parameters/lengthkeyparameter.py +2 -1
- odxtools/parameters/matchingrequestparameter.py +8 -11
- odxtools/parameters/nrcconstparameter.py +11 -21
- odxtools/parameters/parameter.py +4 -18
- odxtools/parameters/parameterwithdop.py +14 -29
- odxtools/parameters/physicalconstantparameter.py +7 -9
- odxtools/parameters/reservedparameter.py +17 -38
- odxtools/parameters/systemparameter.py +6 -5
- odxtools/parameters/tableentryparameter.py +6 -5
- odxtools/parameters/tablekeyparameter.py +8 -15
- odxtools/parameters/tablestructparameter.py +11 -12
- odxtools/parameters/valueparameter.py +9 -24
- odxtools/paramlengthinfotype.py +11 -9
- odxtools/physicaldimension.py +1 -1
- odxtools/physicaltype.py +2 -2
- odxtools/response.py +7 -3
- odxtools/singleecujob.py +48 -22
- odxtools/standardlengthtype.py +11 -6
- odxtools/uds.py +1 -1
- odxtools/unit.py +5 -5
- odxtools/unitgroup.py +1 -1
- odxtools/unitspec.py +2 -2
- odxtools/version.py +13 -3
- odxtools/write_pdx_file.py +7 -4
- {odxtools-5.3.1.dist-info → odxtools-6.0.1.dist-info}/METADATA +7 -5
- {odxtools-5.3.1.dist-info → odxtools-6.0.1.dist-info}/RECORD +87 -88
- odxtools/positioneddataobjectproperty.py +0 -74
- {odxtools-5.3.1.dist-info → odxtools-6.0.1.dist-info}/LICENSE +0 -0
- {odxtools-5.3.1.dist-info → odxtools-6.0.1.dist-info}/WHEEL +0 -0
- {odxtools-5.3.1.dist-info → odxtools-6.0.1.dist-info}/entry_points.txt +0 -0
- {odxtools-5.3.1.dist-info → odxtools-6.0.1.dist-info}/top_level.txt +0 -0
@@ -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, Tuple
|
4
4
|
from xml.etree import ElementTree
|
5
5
|
|
6
6
|
from .createsdgs import create_sdgs_from_et
|
@@ -11,7 +11,7 @@ from .encodestate import EncodeState
|
|
11
11
|
from .environmentdata import EnvironmentData
|
12
12
|
from .exceptions import DecodeError, EncodeError, odxrequire
|
13
13
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
|
14
|
-
from .odxtypes import odxstr_to_bool
|
14
|
+
from .odxtypes import ParameterValue, odxstr_to_bool
|
15
15
|
from .utils import dataclass_fields_asdict
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
@@ -93,7 +93,7 @@ class EnvironmentDataDescription(DopBase):
|
|
93
93
|
for ed in self.env_datas:
|
94
94
|
ed._resolve_snrefs(diag_layer)
|
95
95
|
|
96
|
-
def convert_physical_to_bytes(self, physical_value, encode_state: EncodeState,
|
96
|
+
def convert_physical_to_bytes(self, physical_value: ParameterValue, encode_state: EncodeState,
|
97
97
|
bit_position: int) -> bytes:
|
98
98
|
"""Convert the physical value into bytes.
|
99
99
|
|
@@ -102,7 +102,9 @@ class EnvironmentDataDescription(DopBase):
|
|
102
102
|
"""
|
103
103
|
raise EncodeError("EnvironmentDataDescription DOPs cannot be encoded or decoded")
|
104
104
|
|
105
|
-
def convert_bytes_to_physical(self,
|
105
|
+
def convert_bytes_to_physical(self,
|
106
|
+
decode_state: DecodeState,
|
107
|
+
bit_position: int = 0) -> Tuple[ParameterValue, int]:
|
106
108
|
"""Extract the bytes from the PDU and convert them to the physical value.
|
107
109
|
|
108
110
|
Since environmental data is supposed to never appear on the
|
odxtools/field.py
CHANGED
@@ -2,11 +2,10 @@ from dataclasses import dataclass
|
|
2
2
|
from typing import TYPE_CHECKING, List, Optional
|
3
3
|
from xml.etree import ElementTree
|
4
4
|
|
5
|
-
from .environmentdatadescription import EnvironmentDataDescription
|
6
5
|
from .basicstructure import BasicStructure
|
7
6
|
from .createsdgs import create_sdgs_from_et
|
8
7
|
from .dopbase import DopBase
|
9
|
-
from .
|
8
|
+
from .environmentdatadescription import EnvironmentDataDescription
|
10
9
|
from .exceptions import odxassert, odxrequire
|
11
10
|
from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkRef
|
12
11
|
from .odxtypes import odxstr_to_bool
|
@@ -67,12 +66,8 @@ class Field(DopBase):
|
|
67
66
|
"""may be a Structure or a env-data-desc"""
|
68
67
|
return odxrequire(self._structure, "EnvironmentDataDescription is not supported")
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
return self.structure.bit_length
|
73
|
-
|
74
|
-
def convert_physical_to_internal(self, physical_value):
|
75
|
-
return self.structure.convert_physical_to_internal(physical_value)
|
69
|
+
def get_static_bit_length(self) -> Optional[int]:
|
70
|
+
return None
|
76
71
|
|
77
72
|
def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
|
78
73
|
"""Recursively resolve any odxlinks references"""
|
odxtools/isotp_state_machine.py
CHANGED
@@ -5,7 +5,8 @@ import asyncio
|
|
5
5
|
import re
|
6
6
|
import sys
|
7
7
|
from enum import IntEnum
|
8
|
-
from
|
8
|
+
from io import TextIOBase
|
9
|
+
from typing import AsyncGenerator, Iterable, List, Optional, TextIO, Tuple, Union
|
9
10
|
|
10
11
|
import bitstruct
|
11
12
|
import can
|
@@ -26,8 +27,10 @@ class IsoTp(IntEnum):
|
|
26
27
|
|
27
28
|
class IsoTpStateMachine:
|
28
29
|
can_normal_frame_re = re.compile(
|
29
|
-
"([a-zA-Z0-9_-]*) *([0-9A-Fa-f ]*)
|
30
|
-
can_log_frame_re = re.compile("
|
30
|
+
"([a-zA-Z0-9_-]*) *([0-9A-Fa-f ]*) *\\[[0-9]+\\] *([ 0-9A-Fa-f]+)")
|
31
|
+
can_log_frame_re = re.compile("\\([0-9.]*\\) *([a-zA-Z0-9_-]*) ([0-9A-Fa-f]+)#([0-9A-Fa-f]+)")
|
32
|
+
can_fd_log_frame_re = re.compile(
|
33
|
+
"\\([0-9.]*\\) *([a-zA-Z0-9_-]*) ([0-9A-Fa-f]+)##[0-9A-Fa-f]([0-9A-Fa-f]+)")
|
31
34
|
|
32
35
|
def __init__(self, can_rx_ids: Union[int, List[int]]):
|
33
36
|
if isinstance(can_rx_ids, int):
|
@@ -103,7 +106,8 @@ class IsoTpStateMachine:
|
|
103
106
|
else:
|
104
107
|
self.on_frame_type_error(telegram_idx, frame_type)
|
105
108
|
|
106
|
-
async def read_telegrams(self, bus
|
109
|
+
async def read_telegrams(self, bus: Union[can.Bus,
|
110
|
+
TextIO]) -> AsyncGenerator[Tuple[int, bytes], None]:
|
107
111
|
"""This is equivalent to the :py:meth:`file.readlines()` method, but
|
108
112
|
it yields ISO-TP telegrams instead of lines.
|
109
113
|
|
@@ -112,12 +116,8 @@ class IsoTpStateMachine:
|
|
112
116
|
:param bus: Input file or socket of can bus to read the can frames
|
113
117
|
"""
|
114
118
|
|
115
|
-
if
|
116
|
-
#
|
117
|
-
# exhibits a set_filters() method is assumed to be a can
|
118
|
-
# bus object.
|
119
|
-
|
120
|
-
# creat an "on receive" event for the can bus
|
119
|
+
if isinstance(bus, can.Bus):
|
120
|
+
# create an "on receive" event for the can bus
|
121
121
|
rx_event = asyncio.Event()
|
122
122
|
loop = asyncio.get_running_loop()
|
123
123
|
loop.add_reader(bus, rx_event.set)
|
@@ -126,11 +126,13 @@ class IsoTpStateMachine:
|
|
126
126
|
await rx_event.wait()
|
127
127
|
|
128
128
|
msg = bus.recv()
|
129
|
+
if msg is None:
|
130
|
+
continue
|
129
131
|
for tmp in self.decode_rx_frame(msg.arbitration_id, msg.data):
|
130
132
|
yield tmp
|
131
133
|
else:
|
134
|
+
assert isinstance(bus, TextIOBase)
|
132
135
|
# input is a file
|
133
|
-
|
134
136
|
while bus:
|
135
137
|
cur_line = bus.readline()
|
136
138
|
if cur_line == "":
|
@@ -141,13 +143,14 @@ class IsoTpStateMachine:
|
|
141
143
|
frame_id = int(m.group(2), 16)
|
142
144
|
|
143
145
|
frame_data_formatted = m.group(3).strip()
|
144
|
-
frame_data = bytearray(
|
145
|
-
map(lambda x: int(x, 16), frame_data_formatted.split(" ")))
|
146
|
+
frame_data = bytearray([int(x, 16) for x in frame_data_formatted.split(" ")])
|
146
147
|
|
147
148
|
for tmp in self.decode_rx_frame(frame_id, frame_data):
|
148
149
|
yield tmp
|
149
150
|
|
150
|
-
elif m := self.can_log_frame_re.match(
|
151
|
+
elif (m := self.can_log_frame_re.match(
|
152
|
+
cur_line.strip())) or (m := self.can_fd_log_frame_re.match(
|
153
|
+
cur_line.strip())):
|
151
154
|
#frame_interface = m.group(2)
|
152
155
|
frame_id = int(m.group(2), 16)
|
153
156
|
|
@@ -156,7 +159,7 @@ class IsoTpStateMachine:
|
|
156
159
|
frame_data_formatted[i:i + 2]
|
157
160
|
for i in range(0, len(frame_data_formatted), 2)
|
158
161
|
]
|
159
|
-
frame_data = bytearray(
|
162
|
+
frame_data = bytearray([int(x, 16) for x in frame_data_list])
|
160
163
|
|
161
164
|
for tmp in self.decode_rx_frame(frame_id, frame_data):
|
162
165
|
yield tmp
|
@@ -166,14 +169,14 @@ class IsoTpStateMachine:
|
|
166
169
|
f"Warning: unrecognized frame format: '{cur_line.strip()}'",
|
167
170
|
file=sys.stderr)
|
168
171
|
|
169
|
-
def can_rx_id(self, telegram_idx):
|
172
|
+
def can_rx_id(self, telegram_idx: int) -> int:
|
170
173
|
"""Given a Telegram index, returns the CAN ID for receiving data.
|
171
174
|
|
172
175
|
:raises IndexError: The telegram index is invalid.
|
173
176
|
"""
|
174
177
|
return self._can_rx_ids[telegram_idx]
|
175
178
|
|
176
|
-
def telegram_data(self, telegram_idx):
|
179
|
+
def telegram_data(self, telegram_idx: int) -> Optional[bytes]:
|
177
180
|
"""Given a Telegram index, returns the data received for this telegram
|
178
181
|
so far.
|
179
182
|
|
@@ -184,31 +187,32 @@ class IsoTpStateMachine:
|
|
184
187
|
##############
|
185
188
|
# Callbacks
|
186
189
|
##############
|
187
|
-
def on_single_frame(self, telegram_idx, frame_payload):
|
188
|
-
"""
|
190
|
+
def on_single_frame(self, telegram_idx: int, frame_payload: bytes) -> None:
|
191
|
+
"""Callback method for when an ISO-TP message of type "single frame" has been received"""
|
189
192
|
pass
|
190
193
|
|
191
|
-
def on_first_frame(self, telegram_idx, frame_payload):
|
192
|
-
"""
|
194
|
+
def on_first_frame(self, telegram_idx: int, frame_payload: bytes) -> None:
|
195
|
+
"""Callback method for when an ISO-TP message of type "first frame" has been received"""
|
193
196
|
pass
|
194
197
|
|
195
|
-
def on_consecutive_frame(self, telegram_idx, segment_idx,
|
196
|
-
|
198
|
+
def on_consecutive_frame(self, telegram_idx: int, segment_idx: int,
|
199
|
+
frame_payload: bytes) -> None:
|
200
|
+
"""Callback method for when an ISO-TP message of type "consecutive frame" has been received"""
|
197
201
|
pass
|
198
202
|
|
199
|
-
def on_flow_control_frame(self, telegram_idx, flow_control_flag):
|
203
|
+
def on_flow_control_frame(self, telegram_idx: int, flow_control_flag: int) -> None:
|
200
204
|
"""Method called when an ISO-TP message of type "flow control frame" has been received"""
|
201
205
|
pass
|
202
206
|
|
203
|
-
def on_sequence_error(self, telegram_idx, expected_idx, rx_idx):
|
207
|
+
def on_sequence_error(self, telegram_idx: int, expected_idx: int, rx_idx: int) -> None:
|
204
208
|
"""Method called when a frame with an unexpected sequence index has been received"""
|
205
209
|
pass
|
206
210
|
|
207
|
-
def on_frame_type_error(self, telegram_idx, frame_type):
|
211
|
+
def on_frame_type_error(self, telegram_idx: int, frame_type: int) -> None:
|
208
212
|
"""Method called when a frame exhibiting an unknown frame type has been received"""
|
209
213
|
pass
|
210
214
|
|
211
|
-
def on_telegram_complete(self, telegram_idx, telegram_payload):
|
215
|
+
def on_telegram_complete(self, telegram_idx: int, telegram_payload: bytes) -> None:
|
212
216
|
"""Method called when an ISO-TP telegram has been fully received"""
|
213
217
|
pass
|
214
218
|
|
@@ -219,7 +223,12 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
|
|
219
223
|
receive ISO-TP messages actively instead of just snooping in on
|
220
224
|
other people's conversations."""
|
221
225
|
|
222
|
-
def __init__(self,
|
226
|
+
def __init__(self,
|
227
|
+
can_bus: can.Bus,
|
228
|
+
can_rx_ids: List[int],
|
229
|
+
can_tx_ids: List[int],
|
230
|
+
padding_size: int = 0,
|
231
|
+
padding_value: int = 0xAA):
|
223
232
|
self._can_bus = can_bus
|
224
233
|
|
225
234
|
if isinstance(can_tx_ids, int):
|
@@ -231,14 +240,13 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
|
|
231
240
|
|
232
241
|
super().__init__(can_rx_ids)
|
233
242
|
|
234
|
-
assert isinstance(self._can_tx_ids, list)
|
235
243
|
assert len(self._can_rx_ids) == len(self._can_tx_ids)
|
236
244
|
assert set(self._can_rx_ids).isdisjoint(set(self._can_tx_ids)) # correct?
|
237
245
|
|
238
|
-
self._block_size = [None] * len(self._can_rx_ids)
|
239
|
-
self._frames_received = [None] * len(self._can_rx_ids)
|
246
|
+
self._block_size: List[Optional[int]] = [None] * len(self._can_rx_ids)
|
247
|
+
self._frames_received: List[Optional[int]] = [None] * len(self._can_rx_ids)
|
240
248
|
|
241
|
-
def can_tx_id(self, telegram_idx):
|
249
|
+
def can_tx_id(self, telegram_idx: int) -> int:
|
242
250
|
"""Given a Telegram index, returns the CAN ID for sending data.
|
243
251
|
|
244
252
|
:raises TypeError: No transmission IDs specified (e.g.,
|
@@ -247,7 +255,7 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
|
|
247
255
|
"""
|
248
256
|
return self._can_tx_ids[telegram_idx]
|
249
257
|
|
250
|
-
def on_single_frame(self, telegram_idx, frame_payload):
|
258
|
+
def on_single_frame(self, telegram_idx: int, frame_payload: bytes) -> None:
|
251
259
|
# send ACK
|
252
260
|
#rx_id = self.can_rx_id(telegram_idx)
|
253
261
|
tx_id = self.can_tx_id(telegram_idx)
|
@@ -266,7 +274,7 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
|
|
266
274
|
|
267
275
|
super().on_first_frame(telegram_idx, frame_payload)
|
268
276
|
|
269
|
-
def on_first_frame(self, telegram_idx, frame_payload):
|
277
|
+
def on_first_frame(self, telegram_idx: int, frame_payload: bytes) -> None:
|
270
278
|
# send ACK
|
271
279
|
#rx_id = self.can_rx_id(telegram_idx)
|
272
280
|
tx_id = self.can_tx_id(telegram_idx)
|
@@ -288,12 +296,18 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
|
|
288
296
|
|
289
297
|
super().on_first_frame(telegram_idx, frame_payload)
|
290
298
|
|
291
|
-
def on_consecutive_frame(self, telegram_idx, segment_idx,
|
292
|
-
|
299
|
+
def on_consecutive_frame(self, telegram_idx: int, segment_idx: int,
|
300
|
+
frame_payload: bytes) -> None:
|
301
|
+
num_received = self._frames_received[telegram_idx]
|
302
|
+
if num_received is None:
|
303
|
+
# consequtive frame received before a first frame.
|
304
|
+
# TODO (?): throw an exception
|
305
|
+
return
|
306
|
+
self._frames_received[telegram_idx] = num_received + 1
|
293
307
|
|
294
308
|
# send new ACK if necessary
|
295
309
|
block_size = self._block_size[telegram_idx]
|
296
|
-
if
|
310
|
+
if block_size is not None and num_received >= block_size:
|
297
311
|
#rx_id = self.can_rx_id(telegram_idx)
|
298
312
|
tx_id = self.can_tx_id(telegram_idx)
|
299
313
|
min_separation_time = 0 # ms
|
@@ -310,7 +324,7 @@ class IsoTpActiveDecoder(IsoTpStateMachine):
|
|
310
324
|
|
311
325
|
super().on_consecutive_frame(telegram_idx, segment_idx, frame_payload)
|
312
326
|
|
313
|
-
def _send_can_message(self, can_tx_id, payload):
|
327
|
+
def _send_can_message(self, can_tx_id: int, payload: bytes) -> None:
|
314
328
|
if len(payload) < self._padding_size:
|
315
329
|
payload = bytes(payload) + bytes([self._padding_value] *
|
316
330
|
(self._padding_size - len(payload)))
|
@@ -1,19 +1,19 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any, Tuple
|
4
4
|
|
5
5
|
from .decodestate import DecodeState
|
6
6
|
from .diagcodedtype import DctType, DiagCodedType
|
7
7
|
from .encodestate import EncodeState
|
8
8
|
from .exceptions import odxassert, odxraise
|
9
|
-
from .odxtypes import DataType
|
9
|
+
from .odxtypes import AtomicOdxType, DataType
|
10
10
|
|
11
11
|
|
12
12
|
@dataclass
|
13
13
|
class LeadingLengthInfoType(DiagCodedType):
|
14
14
|
bit_length: int
|
15
15
|
|
16
|
-
def __post_init__(self):
|
16
|
+
def __post_init__(self) -> None:
|
17
17
|
odxassert(self.bit_length > 0,
|
18
18
|
"A Leading length info type with bit length == 0 does not make sense.")
|
19
19
|
odxassert(
|
@@ -53,13 +53,15 @@ class LeadingLengthInfoType(DiagCodedType):
|
|
53
53
|
|
54
54
|
return length_byte + value_byte
|
55
55
|
|
56
|
-
def convert_bytes_to_internal(self,
|
56
|
+
def convert_bytes_to_internal(self,
|
57
|
+
decode_state: DecodeState,
|
58
|
+
bit_position: int = 0) -> Tuple[AtomicOdxType, int]:
|
57
59
|
coded_message = decode_state.coded_message
|
58
60
|
|
59
61
|
# Extract length of the parameter value
|
60
62
|
byte_length, byte_position = self._extract_internal(
|
61
63
|
coded_message=coded_message,
|
62
|
-
byte_position=decode_state.
|
64
|
+
byte_position=decode_state.cursor_position,
|
63
65
|
bit_position=bit_position,
|
64
66
|
bit_length=self.bit_length,
|
65
67
|
base_data_type=DataType.A_UINT32, # length is an integer
|
@@ -72,7 +74,7 @@ class LeadingLengthInfoType(DiagCodedType):
|
|
72
74
|
# Extract actual value
|
73
75
|
# TODO: The returned value is None if the byte_length is 0. Maybe change it
|
74
76
|
# to some default value like an empty bytearray() or 0?
|
75
|
-
value,
|
77
|
+
value, cursor_position = self._extract_internal(
|
76
78
|
coded_message=coded_message,
|
77
79
|
byte_position=byte_position,
|
78
80
|
bit_position=0,
|
@@ -81,4 +83,4 @@ class LeadingLengthInfoType(DiagCodedType):
|
|
81
83
|
is_highlow_byte_order=self.is_highlow_byte_order,
|
82
84
|
)
|
83
85
|
|
84
|
-
return value,
|
86
|
+
return value, cursor_position
|
odxtools/load_file.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
|
+
from .database import Database
|
2
3
|
from .load_odx_d_file import load_odx_d_file
|
3
4
|
from .load_pdx_file import load_pdx_file
|
4
5
|
|
5
6
|
|
6
|
-
def load_file(file_name: str):
|
7
|
+
def load_file(file_name: str) -> Database:
|
7
8
|
if file_name.lower().endswith(".pdx"):
|
8
9
|
return load_pdx_file(file_name)
|
9
10
|
elif file_name.lower().endswith(".odx-d"):
|
odxtools/load_odx_d_file.py
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from .database import Database
|
3
|
-
from .globals import logger
|
4
3
|
|
5
4
|
|
6
|
-
def load_odx_d_file(odx_d_file_name: str):
|
7
|
-
|
8
|
-
logger.info(f"--- --- --- Done with parsing --- --- ---")
|
9
|
-
return container
|
5
|
+
def load_odx_d_file(odx_d_file_name: str) -> Database:
|
6
|
+
return Database(odx_d_file_name=odx_d_file_name)
|
odxtools/load_pdx_file.py
CHANGED
@@ -2,11 +2,7 @@
|
|
2
2
|
from zipfile import ZipFile
|
3
3
|
|
4
4
|
from .database import Database
|
5
|
-
from .globals import logger
|
6
5
|
|
7
6
|
|
8
|
-
def load_pdx_file(pdx_file: str):
|
9
|
-
|
10
|
-
container = Database(pdx_zip=u)
|
11
|
-
logger.info(f"--- --- --- Done with parsing --- --- ---")
|
12
|
-
return container
|
7
|
+
def load_pdx_file(pdx_file: str) -> Database:
|
8
|
+
return Database(pdx_zip=ZipFile(pdx_file))
|
odxtools/message.py
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import TYPE_CHECKING
|
3
|
+
from typing import TYPE_CHECKING, Union
|
4
|
+
|
5
|
+
from deprecation import deprecated
|
4
6
|
|
5
7
|
from .odxtypes import ParameterValue, ParameterValueDict
|
6
8
|
|
7
9
|
if TYPE_CHECKING:
|
8
10
|
from .diagservice import DiagService
|
9
|
-
from .
|
11
|
+
from .request import Request
|
12
|
+
from .response import Response
|
10
13
|
|
11
14
|
|
12
15
|
@dataclass
|
@@ -21,8 +24,13 @@ class Message:
|
|
21
24
|
|
22
25
|
coded_message: bytes
|
23
26
|
service: "DiagService"
|
24
|
-
|
27
|
+
coding_object: Union["Request", "Response"]
|
25
28
|
param_dict: ParameterValueDict
|
26
29
|
|
27
30
|
def __getitem__(self, key: str) -> ParameterValue:
|
28
31
|
return self.param_dict[key]
|
32
|
+
|
33
|
+
@property
|
34
|
+
@deprecated("use .coding_object")
|
35
|
+
def structure(self) -> Union["Request", "Response"]:
|
36
|
+
return self.coding_object
|