@@ -628,6 +628,8 @@ def __init__(self, sdo_client, index, subindex=0, size=None, request_crc_support
628
628
self ._seqno = 0
629
629
self ._crc = sdo_client .crc_cls ()
630
630
self ._last_bytes_sent = 0
631
+ self ._current_block = []
632
+ self ._retransmitting = False
631
633
command = REQUEST_BLOCK_DOWNLOAD | INITIATE_BLOCK_TRANSFER
632
634
if request_crc_support :
633
635
command |= CRC_SUPPORTED
@@ -708,7 +710,10 @@ def send(self, b, end=False):
708
710
request [1 :len (b ) + 1 ] = b
709
711
self .sdo_client .send_request (request )
710
712
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 :
712
717
# Calculate CRC
713
718
self ._crc .process (b )
714
719
if self ._seqno >= self ._blksize :
@@ -731,14 +736,37 @@ def _block_ack(self):
731
736
raise SdoCommunicationError ("Server did not respond with a "
732
737
"block download response" )
733
738
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 = []
738
745
logger .debug ("All %d sequences were received successfully" , ackseq )
739
746
logger .debug ("Server requested a block size of %d" , blksize )
740
747
self ._blksize = blksize
741
748
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
742
770
743
771
def close (self ):
744
772
"""Closes the stream."""
0 commit comments