Skip to content

Commit

Permalink
Merge pull request #77 from khauersp/memory-access
Browse files Browse the repository at this point in the history
Expand Memory access fix
  • Loading branch information
snideto authored Jun 8, 2024
2 parents 44b714c + 9675f85 commit e5a0b5e
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 68 deletions.
52 changes: 36 additions & 16 deletions j1939/Dm14Server.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,18 @@ def _wait_for_data(self) -> None:
self.sa,
)
self._send_dm16()
self.proceed = True
self.state = ResponseState.SEND_OPERATION_COMPLETE
self._ca.subscribe(self.parse_dm14)
self._send_dm15(
self.length,
self.direct,
self.status,
self.state,
self.object_count,
self.sa,
)
if (len(self.data)) <= 8:
self.proceed = True
self.state = ResponseState.SEND_OPERATION_COMPLETE
self._ca.subscribe(self.parse_dm14)
self._send_dm15(
self.length,
self.direct,
self.status,
self.state,
self.object_count,
self.sa,
)
else:
self._ca.subscribe(self._parse_dm16)
self._send_dm15(
Expand Down Expand Up @@ -104,7 +105,7 @@ def parse_dm14(
data[0],
sa,
j1939.ParameterGroupNumber.PGN.DM15,
self.error if self.error is not 0x00 else 0x2,
self.error if self.error != 0x00 else 0x2,
0x7,
)
self.set_busy(False)
Expand Down Expand Up @@ -221,11 +222,12 @@ def _send_dm16(self) -> None:
data = []
byte_count = len(self.data)
data.append(0xFF if byte_count > 7 else byte_count)

for i in range(byte_count):
for i in range((byte_count)):
data.append(self.data[i])

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

def _parse_dm16(
Expand Down Expand Up @@ -300,9 +302,28 @@ def verify_key(self, seed: int, key: int) -> bool:
:param int seed: seed
:param int key: key
"""
test = self._key_from_seed(seed)
return True if self._key_from_seed(seed) == key else False

def reset_query(self) -> None:
"""
Resets query to initial state
"""
self.state = ResponseState.IDLE
self.sa = None
self.seed = None
self.key = None
self._busy = False
self.address = None
self.length = 8
self.proceed = False
self.data = []
self.error = 0x00
self.edcp = 0x07
self.status = j1939.Dm15Status.PROCEED.value
self.direct = 0
self._ca.unsubscribe(self.parse_dm14)
self._ca.unsubscribe(self._parse_dm16)

def respond(
self,
proceed: bool,
Expand Down Expand Up @@ -336,5 +357,4 @@ def respond(
mem_data = None
if self.state == ResponseState.WAIT_FOR_DM16:
mem_data = self.data_queue.get(block=True, timeout=3)

return mem_data
3 changes: 3 additions & 0 deletions j1939/j1939_21.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ def _process_tp_cm(self, mid, dest_address, data, timestamp):
self.__send_tp_abort(dest_address, src_address, self.ConnectionAbortReason.RESOURCES, pgn)
return
# TODO: should we inform the application about the successful transmission?
# Notify subscribers here to be used for the memory access server to know when to send operation complete
self.__notify_subscribers(mid.priority,pgn,mid.source_address,dest_address,timestamp,data)

self._snd_buffer[buffer_hash]['state'] = self.SendBufferState.TRANSMISSION_FINISHED
self._snd_buffer[buffer_hash]['deadline'] = time.time()
self.__job_thread_wakeup()
Expand Down
2 changes: 2 additions & 0 deletions j1939/j1939_22.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ def _process_tp_cm(self, mid, dest_address, data, timestamp):
self.__put_rts_cts_session(session_num)
return
# TODO: should we inform the application about the successful transmission?
# Notify subscribers here to be used for the memory access server to know when to send operation complete
self.__notify_subscribers(mid.priority, pgn, mid.source_address, dest_address, timestamp, data)
self._snd_buffer[buffer_hash]['state'] = self.SendBufferState.EOM_ACK_RECEIVED
self._snd_buffer[buffer_hash]['deadline'] = time.time() # wake up immediately
self.__job_thread_wakeup()
Expand Down
131 changes: 79 additions & 52 deletions j1939/memory_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,52 +36,30 @@ def _listen_for_dm14(
:param timestamp: Timestamp of the message
:param data: Data of the PDU
"""
match self.state:
case DMState.IDLE:
self.state = DMState.REQUEST_STARTED
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
if not self.seed_security:
self.state = DMState.WAIT_RESPONSE
self._ca.unsubscribe(self._listen_for_dm14)
if self._proceed_function is not None:
self.proceed = self._proceed_function(
self.server.command,
self.server.address,
self.server.pointer_type,
self.server.length,
self.server.object_count,
0xFFFF, # placeholder for key
self.server.sa,
self.server.access_level,
0x0, # placeholder for seed
) # call proceed function and pass in basic parameters
if self.proceed:
self._notify_query_received() # notify incoming request
else:
self.server.error = 0x100
self.server.set_busy(True)
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
self.server.set_busy(False)
self.state = DMState.IDLE
self.server.error = 0x0

case DMState.REQUEST_STARTED:
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
if self.server.state == j1939.ResponseState.SEND_PROCEED:
self.state = DMState.WAIT_RESPONSE
if self.seed_security:
if self.server.verify_key(self.server.seed, self.server.key):
if pgn == j1939.ParameterGroupNumber.PGN.DM14:
match self.state:
case DMState.IDLE:
if self.server.state.value == DMState.IDLE.value:
self.state = DMState.REQUEST_STARTED
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
if not self.seed_security:
self.state = DMState.WAIT_RESPONSE
self._ca.unsubscribe(self._listen_for_dm14)
if self._proceed_function is not None:
self.proceed = self._proceed_function(
self.server.command,
self.server.address,
int.from_bytes(
bytes=self.server.address,
byteorder="little",
signed=False,
),
self.server.pointer_type,
self.server.length,
self.server.object_count,
self.server.key,
0xFFFF, # placeholder for key
self.server.sa,
self.server.access_level,
self.server.seed,
0x0, # placeholder for seed
) # call proceed function and pass in basic parameters
if self.proceed:
self._notify_query_received() # notify incoming request
Expand All @@ -92,22 +70,62 @@ def _listen_for_dm14(
priority, pgn, sa, timestamp, data
)
self.server.set_busy(False)
self.server.reset_query()
self.state = DMState.IDLE
self.server.error = 0x0
else:
self.server.error = 0x1003
self.server.set_busy(True)
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
self.server.set_busy(False)
self.state = DMState.IDLE
self.server.error = 0x0

case DMState.WAIT_QUERY:
self.server.set_busy(True)
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
self.server.set_busy(False)
case _:
pass
case DMState.REQUEST_STARTED:
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
if self.server.state == j1939.ResponseState.SEND_PROCEED:
self.state = DMState.WAIT_RESPONSE
if self.seed_security:
if self.server.verify_key(
self.server.seed, self.server.key
):
if self._proceed_function is not None:
self.proceed = self._proceed_function(
self.server.command,
int.from_bytes(
bytes=self.server.address,
byteorder="little",
signed=False,
),
self.server.pointer_type,
self.server.length,
self.server.object_count,
self.server.key,
self.server.sa,
self.server.access_level,
self.server.seed,
) # call proceed function and pass in basic parameters
if self.proceed:
self._notify_query_received() # notify incoming request
else:
self.server.error = 0x100
self.server.set_busy(True)
self.server.parse_dm14(
priority, pgn, sa, timestamp, data
)
self.server.set_busy(False)
self.server.reset_query()
self.state = DMState.IDLE
self.server.error = 0x0
else:
self.server.error = 0x1003
self.server.set_busy(True)
self.server.parse_dm14(
priority, pgn, sa, timestamp, data
)
self.server.set_busy(False)
self.state = DMState.IDLE
self.server.error = 0x0

case DMState.WAIT_QUERY:
self.server.set_busy(True)
self.server.parse_dm14(priority, pgn, sa, timestamp, data)
self.server.set_busy(False)
case _:
pass

def respond(
self, proceed: bool, data: list = None, error: int = 0xFFFFFF, edcp: int = 0xFF
Expand All @@ -124,7 +142,9 @@ def respond(
if self.state is DMState.WAIT_RESPONSE:
self._ca.unsubscribe(self._listen_for_dm14)
self.state = DMState.IDLE
return self.server.respond(proceed, data, error, edcp)
return_data = self.server.respond(proceed, data, error, edcp)
self._ca.subscribe(self._listen_for_dm14)
return return_data
else:
return data

Expand Down Expand Up @@ -216,3 +236,10 @@ def set_proceed(self, proceed: callable) -> None:
:param callable proceed: proceed function
"""
self._proceed_function = proceed

def reset_query(self) -> None:
"""
reset query for the server
"""
self._ca.subscribe(self._listen_for_dm14)
self.server.reset_query()
1 change: 1 addition & 0 deletions test/test_memory_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def proceed(
:param address: DM14 address
:param pointer_type: DM14 pointer type
:param length: DM14 length
:param object_count: number of objects to read
:param key: key
:param source_addr: DM14 source address of message requesting access
:param access_level: DM14 access level
Expand Down

0 comments on commit e5a0b5e

Please sign in to comment.