@@ -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