Skip to content

Commit e3829fc

Browse files
authored
Adding retransmit functionnality to sdo block download (#324)
1 parent c7ad0a8 commit e3829fc

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

canopen/sdo/client.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,8 @@ def __init__(self, sdo_client, index, subindex=0, size=None, request_crc_support
628628
self._seqno = 0
629629
self._crc = sdo_client.crc_cls()
630630
self._last_bytes_sent = 0
631+
self._current_block = []
632+
self._retransmitting = False
631633
command = REQUEST_BLOCK_DOWNLOAD | INITIATE_BLOCK_TRANSFER
632634
if request_crc_support:
633635
command |= CRC_SUPPORTED
@@ -708,7 +710,10 @@ def send(self, b, end=False):
708710
request[1:len(b) + 1] = b
709711
self.sdo_client.send_request(request)
710712
self.pos += len(b)
711-
if self.crc_supported:
713+
# Add the sent data to the current block buffer
714+
self._current_block.append(b)
715+
# Don't calculate crc if retransmitting
716+
if self.crc_supported and not self._retransmitting:
712717
# Calculate CRC
713718
self._crc.process(b)
714719
if self._seqno >= self._blksize:
@@ -731,14 +736,37 @@ def _block_ack(self):
731736
raise SdoCommunicationError("Server did not respond with a "
732737
"block download response")
733738
if ackseq != self._blksize:
734-
self.sdo_client.abort(0x05040003)
735-
raise SdoCommunicationError(
736-
("%d of %d sequences were received. "
737-
"Retransmission is not supported yet.") % (ackseq, self._blksize))
739+
# Sequence error, try to retransmit
740+
self._retransmit(ackseq, blksize)
741+
# We should be back in sync
742+
return
743+
# Clear the current block buffer
744+
self._current_block = []
738745
logger.debug("All %d sequences were received successfully", ackseq)
739746
logger.debug("Server requested a block size of %d", blksize)
740747
self._blksize = blksize
741748
self._seqno = 0
749+
750+
def _retransmit(self, ackseq, blksize):
751+
"""Retransmit the failed block"""
752+
logger.info(("%d of %d sequences were received. "
753+
"Will start retransmission") % (ackseq, self._blksize))
754+
# Sub blocks betwen ackseq and end of corrupted block need to be resent
755+
# Get the part of the block to resend
756+
block = self._current_block[ackseq:]
757+
# Go back to correct position in stream
758+
self.pos = self.pos - (len(block) * 7)
759+
# Reset the _current_block before starting the retransmission
760+
self._current_block = []
761+
# Reset _seqno and update blksize
762+
self._seqno = 0
763+
self._blksize = blksize
764+
# We are retransmitting
765+
self._retransmitting = True
766+
# Resend the block
767+
for b in block:
768+
self.write(b)
769+
self._retransmitting = False
742770

743771
def close(self):
744772
"""Closes the stream."""

0 commit comments

Comments
 (0)