Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions j1939/Dm14Query.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ def _wait_for_data(self) -> None:
"""
assert self.state is QueryState.WAIT_FOR_SEED
if self.command is Command.WRITE:
self._send_dm16()
self.state = QueryState.WAIT_FOR_OPER_COMPLETE
self._send_dm16()
else:
self.state = QueryState.WAIT_FOR_DM16
self._ca.unsubscribe(self._parse_dm15)
Expand All @@ -75,9 +75,9 @@ def _send_dm14(self, key_or_user_level: int) -> None:
self._pgn = j1939.ParameterGroupNumber.PGN.DM14
pointer = self.address.to_bytes(length=4, byteorder="little")
data = []
data.append(self.object_count)
data.append(self.object_count & 0xFF)
data.append(
(self.direct << 4) + (self.command.value << 1) + 1
((self.object_count >> 3) & 0xE0) + (self.direct << 4) + (self.command.value << 1) + 1
) # (SAE reserved = 1)
for octet in pointer:
data.append(octet)
Expand All @@ -95,8 +95,7 @@ def _send_dm16(self) -> None:
data = []
byte_count = len(self.bytes)
data.append(0xFF if byte_count > 7 else byte_count)
for i in range(byte_count):
data.append(self.bytes[i])
data.extend(self.bytes)
self._ca.send_pgn(
0, (self._pgn >> 8) & 0xFF, self._dest_address & 0xFF, 6, data
)
Expand All @@ -114,7 +113,6 @@ def _parse_dm15(
"""
if pgn != j1939.ParameterGroupNumber.PGN.DM15 or sa != self._dest_address:
return
seed = (data[7] << 8) + data[6]
status = (data[1] >> 1) & 7
if (
status is Dm15Status.BUSY.value
Expand All @@ -137,14 +135,15 @@ def _parse_dm15(
)
)
else:
length = data[0]
seed = (data[7] << 8) + data[6]
length = data[0] + ((data[1] & 0xE0) << 3)
if seed == 0xFFFF and length == self.object_count:
self._wait_for_data()
else:
if self.state is QueryState.WAIT_FOR_OPER_COMPLETE:
assert status is Command.OPERATION_COMPLETED.value
self._send_operation_complete()
self.state = QueryState.IDLE
self._send_operation_complete()
self.data_queue.put(self.mem_data)
else:
assert self.state is QueryState.WAIT_FOR_SEED
Expand All @@ -171,8 +170,10 @@ def _parse_dm16(
"""
if pgn != j1939.ParameterGroupNumber.PGN.DM16 or sa != self._dest_address:
return
length = min(data[0], len(data) - 1)
# assert object_count == self.object_count
if data[0] == 0xFF:
length = len(data) - 1
else:
length = min(data[0], 7)
self.mem_data = data[1 : length + 1]
self._ca.unsubscribe(self._parse_dm16)
self._ca.subscribe(self._parse_dm15)
Expand All @@ -194,10 +195,10 @@ def _bytes_to_values(self, raw_bytes: bytearray) -> list:
:param bytearray raw_bytes: bytes received from device
"""
values = []
for i in range(len(raw_bytes) // self.object_byte_size):
for i in range(0, len(raw_bytes), self.object_byte_size):
values.append(
int.from_bytes(
raw_bytes[i : self.object_byte_size],
raw_bytes[i : i + self.object_byte_size],
byteorder="little",
signed=self.signed,
)
Expand Down Expand Up @@ -227,6 +228,7 @@ def read(
:param int max_timeout: max timeout for transaction
"""
assert object_count > 0
assert object_count <= 1784
self._dest_address = dest_address
self.direct = direct
self.address = address
Expand All @@ -235,9 +237,9 @@ def read(
self.signed = signed
self.return_raw_bytes = return_raw_bytes
self.command = Command.READ
self.state = QueryState.WAIT_FOR_SEED
self._ca.subscribe(self._parse_dm15)
self._send_dm14(7)
self.state = QueryState.WAIT_FOR_SEED
# wait for operation completed DM15 message
raw_bytes = None
try:
Expand Down Expand Up @@ -281,9 +283,10 @@ def write(
self.command = Command.WRITE
self.bytes = self._values_to_bytes(values)
self.object_count = len(values)
assert self.object_count <= 1784
self.state = QueryState.WAIT_FOR_SEED
self._ca.subscribe(self._parse_dm15)
self._send_dm14(7)
self.state = QueryState.WAIT_FOR_SEED
# wait for operation completed DM15 message
try:
self.data_queue.get(block=True, timeout=max_timeout)
Expand Down
35 changes: 20 additions & 15 deletions j1939/Dm14Server.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def _wait_for_data(self) -> None:
):
self._ca.unsubscribe(self._parse_dm16)
self._send_dm16()
if (len(self.data)) <= 8:
if (len(self.data)) <= 7:
self.proceed = True
self.state = ResponseState.SEND_OPERATION_COMPLETE
self._ca.subscribe(self.parse_dm14)
Expand All @@ -77,6 +77,8 @@ def _wait_for_data(self) -> None:
self.error,
self.edcp,
)
else:
self.state = ResponseState.WAIT_FOR_DM16
elif (
self.command is j1939.Command.WRITE.value
and self.state == ResponseState.SEND_PROCEED
Expand All @@ -100,6 +102,7 @@ def parse_dm14(
"""
if pgn != j1939.ParameterGroupNumber.PGN.DM14:
return

if (
(self.sa is not None and sa != self.sa)
or (
Expand All @@ -109,10 +112,10 @@ def parse_dm14(
):
self._send_dm15(
self.length,
data[1] >> 4,
(data[1] >> 4) & 0x1,
j1939.Dm15Status.OPERATION_FAILED.value,
j1939.ResponseState.SEND_ERROR,
data[0],
data[0] + ((data[1] & 0xE0) << 3),
sa,
j1939.ParameterGroupNumber.PGN.DM15,
self.error if self.error != 0x00 else 0x2,
Expand All @@ -122,18 +125,17 @@ def parse_dm14(
return

self.length = len(data)
self.direct = data[1] >> 4
self.direct = (data[1] >> 4) & 0x1

match self.state:
case ResponseState.IDLE:
self.pgn = pgn
self.sa = sa
self.status = j1939.Dm15Status.PROCEED.value
self.address = data[2 : (self.length - 2)]
self.direct = data[1] >> 4
self.command = ((data[1] - 1) & 0x0F) >> 1
self.pointer_type = (data[1] >> 4) & 0x1
self.object_count = data[0]
self.object_count = data[0] + ((data[1] & 0xE0) << 3)
self.access_level = (data[self.length - 1] << 8) + data[self.length - 2]
self.data = data
if self._key_from_seed is not None:
Expand All @@ -154,15 +156,15 @@ def parse_dm14(
self.length = len(data)
self.address = data[2 : (self.length - 2)]
self.command = ((data[1] - 1) & 0x0F) >> 1
self.object_count = data[0]
self.object_count = data[0] + ((data[1] & 0xE0) << 3)
self.key = (data[self.length - 1] << 8) + data[self.length - 2]
self.data = data
self.state = ResponseState.SEND_PROCEED

case ResponseState.WAIT_OPERATION_COMPLETE:
self.state = ResponseState.IDLE
self.sa = None
self._ca.unsubscribe(self.parse_dm14)
self.sa = None
self.state = ResponseState.IDLE

case _:
raise ValueError("Invalid state")
Expand Down Expand Up @@ -203,7 +205,8 @@ def _send_dm15(
data[length - 1] = self.seed >> 8

case ResponseState.SEND_PROCEED:
data[0] = object_count
data[0] = object_count & 0xFF
data[1] += (object_count & 0x300) >> 3

case ResponseState.SEND_OPERATION_COMPLETE:
self.command = j1939.Command.OPERATION_COMPLETED.value
Expand Down Expand Up @@ -231,12 +234,11 @@ def _send_dm16(self) -> None:
self._pgn = j1939.ParameterGroupNumber.PGN.DM16
data = []
byte_count = len(self.data)
data.append(0xFF if byte_count > 7 else byte_count)
for i in range((byte_count)):
data.append(self.data[i])

data.append(0xFF if byte_count > 7 else byte_count)
data.extend(self.data)
data.extend([0xFF] * (self.length - byte_count - 1))
if byte_count > 8:
if byte_count > 7:
self._ca.subscribe(self._parse_dm16)
self._ca.send_pgn(0, (self._pgn >> 8) & 0xFF, self.sa & 0xFF, 7, data)

Expand All @@ -255,7 +257,10 @@ def _parse_dm16(
if pgn != j1939.ParameterGroupNumber.PGN.DM16 or sa != self.sa:
return

length = min(data[0], len(data) - 1)
if data[0] == 0xFF:
length = len(data) - 1
else:
length = min(data[0], 7)
self.data_queue.put(data[1 : length + 1])
self._ca.unsubscribe(self._parse_dm16)
self._ca.subscribe(self.parse_dm14)
Expand Down
Loading