Skip to content

Commit

Permalink
Fixed broken single frame transmission in blocking_send mode (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
pylessard authored Aug 2, 2024
1 parent 9bfe34c commit ade21e6
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 6 deletions.
11 changes: 6 additions & 5 deletions isotp/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,8 @@ def _process_rx(self, msg: CanMessage) -> ProcessRxReport:
immediate_tx_msg_required = True

return self.ProcessRxReport(immediate_tx_required=immediate_tx_msg_required, frame_received=frame_complete)



def _process_tx(self) -> ProcessTxReport:
"""Process the transmit state machine"""
output_msg = None # Value outputted. If None, no subsequent call to _process_tx will be done.
Expand Down Expand Up @@ -1076,7 +1077,7 @@ def _process_tx(self) -> ProcessTxReport:
if total_size <= self.params.tx_data_length - size_offset - len(self.address.get_tx_payload_prefix()):
# Will raise if size is not what was requested
payload = self.active_send_request.generator.consume(total_size, enforce_exact=True)

if size_on_first_byte:
msg_data = self.address.get_tx_payload_prefix() + bytearray([0x0 | len(payload)]) + payload
else:
Expand All @@ -1090,7 +1091,8 @@ def _process_tx(self) -> ProcessTxReport:
self.tx_state = self.TxState.TRANSMIT_SF_STANDBY
else:
output_msg = msg_temp

self._stop_sending(success=True)

# Multi frame - First Frame
else:
self.tx_frame_length = total_size
Expand Down Expand Up @@ -1125,7 +1127,6 @@ def _process_tx(self) -> ProcessTxReport:
# This states serves if the rate limiter prevent from starting a new transmission.
# We need to pop the isotp frame to know if the rate limiter must kick, but since the data is already popped,
# we can't stay in IDLE state. So we come here until the rate limiter gives us permission to proceed.

if self.tx_standby_msg is not None:
if len(self.tx_standby_msg.data) <= allowed_bytes:
output_msg = self.tx_standby_msg
Expand All @@ -1151,7 +1152,7 @@ def _process_tx(self) -> ProcessTxReport:
payload = self.active_send_request.generator.consume(payload_length, enforce_exact=False)
if len(payload) > 0: # Corner case. If generator size is a multiple of ll_data_length, we will get an empty payload on last frame.
msg_data = self.address.get_tx_payload_prefix() + bytearray([0x20 | self.tx_seqnum]) + payload
arbitration_id = self.address.get_tx_arbitration_id()
arbitration_id = self.address.get_tx_arbitration_id()
output_msg = self._make_tx_msg(arbitration_id, msg_data)
self.tx_seqnum = (self.tx_seqnum + 1) & 0xF
self.timer_tx_stmin.start()
Expand Down
9 changes: 8 additions & 1 deletion test/test_transport_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,20 @@ def test_blocking_send_error(self):
# Transmission will fail because no flow control
self.layer1.send(bytes([1] * 10), send_timeout=10)

def test_blocking_send(self):
def test_blocking_send_multiframe(self):
self.layer1.params.blocking_send = True
self.layer1.load_params()
# layer2 has a thread to handle reception
self.layer1.send(bytes([1] * 100), send_timeout=5)
self.assert_no_error_reported()

def test_blocking_send_single_frame(self):
self.layer1.params.blocking_send = True
self.layer1.load_params()
# layer2 has a thread to handle reception
self.layer1.send(bytes([1] * 4), send_timeout=5)
self.assert_no_error_reported()

def test_listen_mode_receiver(self):
# listen mode enabled. Address is the receiver address
self.layer2.params.blocksize=5
Expand Down

0 comments on commit ade21e6

Please sign in to comment.