From 62c1064c52016c02b0e22d841310f5c59dd216c0 Mon Sep 17 00:00:00 2001 From: Jacob Christ Date: Fri, 12 Nov 2021 16:57:37 -0800 Subject: [PATCH 1/6] Fixes to get ymodem working with ideas stolen from multi-protocol3.7 --- modem/error.py | 1 + modem/protocol/xmodem.py | 26 +++++++++++++++++++++----- modem/protocol/ymodem.py | 12 +++++++----- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/modem/error.py b/modem/error.py index 4e3e0b6..6c02828 100644 --- a/modem/error.py +++ b/modem/error.py @@ -25,6 +25,7 @@ DEBUG_START_FILENAME = _('Start sending "%s"') DEBUG_TRY_CRC = _('Try CRC mode') DEBUG_TRY_CHECKSUM = _('Try check sum mode') +DEBUG_SEND_PROGRESS = _('Progress: |{}>{:3.0f}%{}|') ERROR_EXPECT_NAK_CRC = ERROR_WHY % _('expected /, got "%02x"') ERROR_EXPECT_SOH_EOT = ERROR_WHY % _('expected /, got "%02x"') diff --git a/modem/protocol/xmodem.py b/modem/protocol/xmodem.py index 804f895..b271013 100644 --- a/modem/protocol/xmodem.py +++ b/modem/protocol/xmodem.py @@ -1,4 +1,6 @@ +from __future__ import print_function import time +import sys from modem import error from modem.base import Modem from modem.const import * @@ -179,7 +181,7 @@ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0): # something went wrong, request retransmission self.putc(NAK) - def _send_stream(self, stream, crc_mode, retry=16, timeout=0): + def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): ''' Sends a stream according to the given protocol dialect: @@ -197,6 +199,7 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0): # SO START DIRECTLY WITH STREAM TRANSMISSION sequence = 1 error_count = 0 + total_sent = 0 while True: data = stream.read(packet_size) @@ -212,8 +215,8 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0): data = data.ljust(packet_size, '\x00') # Calculate CRC or checksum - crc = crc_mode and self.calc_crc16(data) or \ - self.calc_checksum(data) + if crc_mode == 1: crc = self.calc_crc16(data) + else: crc = self.calc_checksum(data) # SENDS PACKET WITH CRC if not self._send_packet(sequence, data, packet_size, crc_mode, @@ -223,9 +226,21 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0): # Next sequence sequence = (sequence + 1) % 0x100 - + if filesize > 0: + total_sent += packet_size + progress = total_sent/filesize + remain = (filesize - total_sent)/filesize + print(error.DEBUG_SEND_PROGRESS.format( + int(50 * progress) * '=', + progress * 100, + int(50 * remain) * ' ', + ), end='\r' + ) + sys.stdout.flush() + + print() # STREAM FINISHED, SEND EOT - log.debug(error.DEBUG_SEND_EOT) + log.debug(error.ERROR_SEND_EOT) if self._send_eot(error_count, retry, timeout): return True else: @@ -308,6 +323,7 @@ def _wait_recv(self, error_count, timeout): cancel = 0 # Loop until the first character is a control character (NAK, CRC) or # we reach the retry limit + retry = 16 while True: char = self.getc(1) if char: diff --git a/modem/protocol/ymodem.py b/modem/protocol/ymodem.py index 4f307cc..c7e20b5 100644 --- a/modem/protocol/ymodem.py +++ b/modem/protocol/ymodem.py @@ -2,6 +2,7 @@ import os from modem.const import * from modem.tools import log +from modem import error from modem.protocol.xmodem import XMODEM @@ -45,9 +46,9 @@ def send(self, pattern, retry=16, timeout=60): sequence = 0 error_count = 0 # REQUIREMENT 1,1a,1b,1c,1d - data = ''.join([os.path.basename(filename), '\x00']) + data = ''.join([os.path.basename(filename), '\x00', str(os.path.getsize(filename)), '\x00']) - log.debug(error.DEBUG_START_FILE % (filename,)) + log.debug(error.DEBUG_START_FILENAME % (filename,)) # Pick a suitable packet length for the filename packet_size = 128 if (len(data) < 128) else 1024 @@ -55,7 +56,7 @@ def send(self, pattern, retry=16, timeout=60): data = data.ljust(packet_size, '\0') # Calculate checksum - crc = self.calc_crc(data) if crc_mode else self.calc_checksum(data) + crc = self.calc_crc16(data) if crc_mode else self.calc_checksum(data) # Emit packet if not self._send_packet(sequence, data, packet_size, crc_mode, @@ -70,12 +71,13 @@ def send(self, pattern, retry=16, timeout=60): return False filedesc = open(filename, 'rb') + filesize = os.path.getsize(filename) # AT THIS POINT # - PACKET 0 WITH METADATA TRANSMITTED # - INITIAL OR ALREADY RECEIVED - if not self._send_stream(filedesc, crc_mode, retry, timeout): + if not self._send_stream(filedesc, crc_mode, retry, timeout, filesize): log.error(error.ABORT_SEND_STREAM) return False @@ -97,7 +99,7 @@ def send(self, pattern, retry=16, timeout=60): error_count = 0 packet_size = 128 data = '\x00' * packet_size - crc = self.calc_crc(data) if crc_mode else self.calc_checksum(data) + crc = self.calc_crc16(data) if crc_mode else self.calc_checksum(data) # Emit packet if not self._send_packet(sequence, data, packet_size, crc_mode, crc, From 22397992e8ba77c9b826a08e9b9952904c152e3e Mon Sep 17 00:00:00 2001 From: Jacob Christ Date: Fri, 12 Nov 2021 17:15:35 -0800 Subject: [PATCH 2/6] Picked up some refactoring from py3.7-multi-protocol by devotip --- modem/protocol/xmodem.py | 126 ++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/modem/protocol/xmodem.py b/modem/protocol/xmodem.py index b271013..b6a77e5 100644 --- a/modem/protocol/xmodem.py +++ b/modem/protocol/xmodem.py @@ -3,7 +3,7 @@ import sys from modem import error from modem.base import Modem -from modem.const import * +from modem import const from modem.tools import log @@ -23,14 +23,14 @@ class XMODEM(Modem): ''' # Protocol identifier - protocol = PROTOCOL_XMODEM + protocol = const.PROTOCOL_XMODEM def abort(self, count=2, timeout=60): ''' Send an abort sequence using CAN bytes. ''' - for counter in xrange(0, count): - self.putc(CAN, timeout) + for counter in range(0, count): + self.putc(const.CAN, timeout) def send(self, stream, retry=16, timeout=60, quiet=0): ''' @@ -49,22 +49,22 @@ def send(self, stream, retry=16, timeout=60, quiet=0): crc_mode = 0 cancel = 0 while True: - char = self.getc(1) - if char: - if char == NAK: + byte = self.getc(1) + if byte: + if byte == const.NAK: crc_mode = 0 break - elif char == CRC: + elif byte == const.CRC: crc_mode = 1 break - elif char == CAN: + elif byte == const.CAN: # We abort if we receive two consecutive bytes if cancel: return False else: cancel = 1 else: - log.error(error.ERROR_EXPECT_NAK_CRC % ord(char)) + log.error(error.ERROR_EXPECT_NAK_CRC % ord(byte)) error_count += 1 if error_count >= retry: @@ -89,7 +89,7 @@ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0): # initiate protocol error_count = 0 - char = 0 + byte = 0 cancel = 0 while True: # first try CRC mode, if this fails, @@ -100,23 +100,23 @@ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0): return None elif crc_mode and error_count < (retry / 2): log.debug(error.DEBUG_TRY_CRC) - if not self.putc(CRC): + if not self.putc(const.CRC): time.sleep(delay) error_count += 1 else: log.debug(error.DEBUG_TRY_CHECKSUM) crc_mode = 0 - if not self.putc(NAK): + if not self.putc(const.NAK): time.sleep(delay) error_count += 1 - char = self.getc(1, timeout) - if char is None: + byte = self.getc(1, timeout) + if byte is None: error_count += 1 continue - elif char in [SOH, STX]: + elif byte in [const.SOH, const.STX]: break - elif char == CAN: + elif byte == const.CAN: if cancel: log.error(error.ABORT_RECV_CAN_CAN) return None @@ -134,21 +134,21 @@ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0): cancel = 0 while True: while True: - if char == SOH: + if byte == const.SOH: packet_size = 128 break - elif char == EOT: + elif byte == const.EOT: # Acknowledge end of transmission - self.putc(ACK) + self.putc(const.ACK) return income_size - elif char == CAN: + elif byte == const.CAN: # We abort if we receive two consecutive bytes if cancel: return None else: cancel = 1 else: - log.debug(error.DEBUG_EXPECT_SOH_EOT % ord(char)) + log.debug(error.DEBUG_EXPECT_SOH_EOT % ord(byte)) error_count += 1 if error_count >= retry: self.abort() @@ -162,16 +162,18 @@ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0): if seq1 == sequence and seq2 == sequence: # sequence is ok, read packet # packet_size + checksum - data = self._check_crc(self.getc(packet_size + 1 + crc_mode), - crc_mode) + data = self._check_crc( + self.getc(packet_size + 1 + crc_mode), + crc_mode + ) # valid data, append chunk if data: income_size += len(data) stream.write(data) - self.putc(ACK) + self.putc(const.ACK) sequence = (sequence + 1) % 0x100 - char = self.getc(1, timeout) + byte = self.getc(1, timeout) continue else: # consume data @@ -179,7 +181,7 @@ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0): log.warning(error.WARNS_SEQUENCE % (sequence, seq1, seq2)) # something went wrong, request retransmission - self.putc(NAK) + self.putc(const.NAK) def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): ''' @@ -193,7 +195,7 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): ''' # Get packet size for current protocol - packet_size = PACKET_SIZE.get(self.protocol, 128) + packet_size = const.PACKET_SIZE.get(self.protocol, 128) # ASSUME THAT I'VE ALREADY RECEIVED THE INITIAL OR # SO START DIRECTLY WITH STREAM TRANSMISSION @@ -208,11 +210,11 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): break # Select optimal packet size when using YMODEM - if self.protocol == PROTOCOL_YMODEM: + if self.protocol == const.PROTOCOL_YMODEM: packet_size = (len(data) <= 128) and 128 or 1024 # Align the packet - data = data.ljust(packet_size, '\x00') + data = data.ljust(packet_size, b'\x00') # Calculate CRC or checksum if crc_mode == 1: crc = self.calc_crc16(data) @@ -255,9 +257,9 @@ def _send_packet(self, sequence, data, packet_size, crc_mode, crc, Return ``True`` on success, ``False`` in case of failure. ''' - start_char = SOH if packet_size == 128 else STX + start_byte = const.SOH if packet_size == 128 else const.STX while True: - self.putc(start_char) + self.putc(start_byte) self.putc(chr(sequence)) self.putc(chr(0xff - sequence)) self.putc(data) @@ -269,12 +271,12 @@ def _send_packet(self, sequence, data, packet_size, crc_mode, crc, self.putc(chr(crc)) # Wait for the - char = self.getc(1, timeout) - if char == ACK: + byte = self.getc(1, timeout) + if byte == const.ACK: # Transmission of the character was successful return True - if char in [None, NAK]: + if byte in [b'', const.NAK]: error_count += 1 if error_count >= retry: # Excessive amounts of retransmissions requested @@ -299,10 +301,10 @@ def _send_eot(self, error_count, retry, timeout): Return ``True`` on success, ``False`` in case of failure. ''' while True: - self.putc(EOT) + self.putc(const.EOT) # Wait for - char = self.getc(1, timeout) - if char == ACK: + byte = self.getc(1, timeout) + if byte == const.ACK: # confirmed return True else: @@ -325,16 +327,16 @@ def _wait_recv(self, error_count, timeout): # we reach the retry limit retry = 16 while True: - char = self.getc(1) - if char: - if char in [NAK, CRC]: - return char - elif char == CAN: + byte = self.getc(1) + if byte: + if byte in [const.NAK, const.CRC]: + return byte + elif byte == const.CAN: # Cancel at two consecutive cancels if cancel: log.error(error.ABORT_RECV_CAN_CAN) self.abort(timeout=timeout) - return False + return None else: log.debug(error.DEBUG_RECV_CAN) cancel = 1 @@ -345,7 +347,7 @@ def _wait_recv(self, error_count, timeout): error_count += 1 if error_count >= retry: self.abort(timeout=timeout) - return False + return None def _recv_stream(self, stream, crc_mode, retry, timeout, delay): ''' @@ -362,11 +364,11 @@ def _recv_stream(self, stream, crc_mode, retry, timeout, delay): cancel = 0 sequence = 1 income_size = 0 - self.putc(CRC) + self.putc(const.CRC) - char = self.getc(1, timeout) + byte = self.getc(1, timeout) while True: - if char is None: + if byte is None: error_count += 1 if error_count >= retry: log.error(error.ABORT_ERROR_LIMIT) @@ -374,17 +376,17 @@ def _recv_stream(self, stream, crc_mode, retry, timeout, delay): return None else: continue - elif char == CAN: + elif byte == const.CAN: if cancel: return None else: cancel = 1 - elif char in [SOH, STX]: - packet_size = 128 if char == SOH else 1024 + elif byte in [const.SOH, const.STX]: + packet_size = 128 if byte == const.SOH else 1024 # Check the requested packet size, only YMODEM has a variable # size - if self.protocol != PROTOCOL_YMODEM and \ - PACKET_SIZE.get(self.protocol) != packet_size: + if self.protocol != const.PROTOCOL_YMODEM and \ + const.PACKET_SIZE.get(self.protocol) != packet_size: log.error(error.ABORT_PACKET_SIZE) self.abort(timeout=timeout) return False @@ -400,32 +402,32 @@ def _recv_stream(self, stream, crc_mode, retry, timeout, delay): # Append data to the stream income_size += len(data) stream.write(data) - self.putc(ACK) + self.putc(const.ACK) sequence = (sequence + 1) % 0x100 # Waiting for new packet - char = self.getc(1, timeout) + byte = self.getc(1, timeout) continue # Sequence numbering is off or CRC is incorrect, request new # packet self.getc(packet_size + 1 + crc_mode) - self.putc(NAK) - elif char == EOT: + self.putc(const.NAK) + elif byte == const.EOT: # We are done, acknowledge - self.putc(ACK) + self.putc(const.ACK) return income_size - elif char == CAN: + elif byte == const.CAN: # Cancel at two consecutive cancels if cancel: return False else: cancel = 1 - self.putc(ACK) - char = self.getc(1, timeout) + self.putc(const.ACK) + byte = self.getc(1, timeout) continue else: - log.debug(error.DEBUG_EXPECT_SOH_EOT % ord(char)) + log.debug(error.DEBUG_EXPECT_SOH_EOT % byte.hex()) error_count += 1 if error_count >= retry: log.error(error.ABORT_ERROR_LIMIT) From 7eb463fa829150d8aebe5fdd6aca67289183546d Mon Sep 17 00:00:00 2001 From: Jacob Christ Date: Fri, 12 Nov 2021 17:23:29 -0800 Subject: [PATCH 3/6] Picked up some refactoring from py3.7-multi-protocol by devotip --- modem/error.py | 4 +- modem/protocol/ymodem.py | 84 +++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/modem/error.py b/modem/error.py index 6c02828..79dc726 100644 --- a/modem/error.py +++ b/modem/error.py @@ -25,7 +25,9 @@ DEBUG_START_FILENAME = _('Start sending "%s"') DEBUG_TRY_CRC = _('Try CRC mode') DEBUG_TRY_CHECKSUM = _('Try check sum mode') -DEBUG_SEND_PROGRESS = _('Progress: |{}>{:3.0f}%{}|') +DEBUG_FILENAME_SENT = _('File name {} sent') +DEBUG_FILE_SENT = _('File {} sent') +DEBUG_SEND_PROGRESS = _('Progress: |{}>{:3.0f}%{}|') ERROR_EXPECT_NAK_CRC = ERROR_WHY % _('expected /, got "%02x"') ERROR_EXPECT_SOH_EOT = ERROR_WHY % _('expected /, got "%02x"') diff --git a/modem/protocol/ymodem.py b/modem/protocol/ymodem.py index c7e20b5..0755cd0 100644 --- a/modem/protocol/ymodem.py +++ b/modem/protocol/ymodem.py @@ -1,9 +1,10 @@ import glob import os -from modem.const import * +import time +from modem import const from modem.tools import log -from modem import error from modem.protocol.xmodem import XMODEM +from modem import error class YMODEM(XMODEM): @@ -12,7 +13,7 @@ class YMODEM(XMODEM): object to write to. ''' - protocol = PROTOCOL_YMODEM + protocol = const.PROTOCOL_YMODEM def send(self, pattern, retry=16, timeout=60): ''' @@ -33,9 +34,9 @@ def send(self, pattern, retry=16, timeout=60): # initialize protocol error_count = 0 crc_mode = 0 - start_char = self._wait_recv(error_count, timeout) - if start_char: - crc_mode = 1 if (start_char == CRC) else 0 + start_byte = self._wait_recv(error_count, timeout) + if start_byte: + crc_mode = 1 if (start_byte == const.CRC) else 0 else: log.error(error.ABORT_PROTOCOL) # Already aborted @@ -46,23 +47,26 @@ def send(self, pattern, retry=16, timeout=60): sequence = 0 error_count = 0 # REQUIREMENT 1,1a,1b,1c,1d - data = ''.join([os.path.basename(filename), '\x00', str(os.path.getsize(filename)), '\x00']) + data = ''.join([os.path.basename(filename), '\x00', str(os.path.getsize(filename))]) log.debug(error.DEBUG_START_FILENAME % (filename,)) # Pick a suitable packet length for the filename packet_size = 128 if (len(data) < 128) else 1024 # Packet padding - data = data.ljust(packet_size, '\0') + data = data.ljust(packet_size, '\0').encode('utf-8') # Calculate checksum - crc = self.calc_crc16(data) if crc_mode else self.calc_checksum(data) + crc = crc_mode and self.calc_crc16(data) or \ + self.calc_checksum(data) # Emit packet - if not self._send_packet(sequence, data, packet_size, crc_mode, - crc, error_count, retry, timeout): + if not self._send_packet( + sequence, data, packet_size, crc_mode, + crc, error_count, retry, timeout): self.abort(timeout=timeout) return False + log.debug(error.DEBUG_FILENAME_SENT.format(filename)) # Wait for before transmitting the file contents error_count = 0 @@ -80,6 +84,7 @@ def send(self, pattern, retry=16, timeout=60): if not self._send_stream(filedesc, crc_mode, retry, timeout, filesize): log.error(error.ABORT_SEND_STREAM) return False + log.debug(error.DEBUG_FILE_SENT.format(filename)) # AT THIS POINT # - FILE CONTENTS TRANSMITTED @@ -98,12 +103,13 @@ def send(self, pattern, retry=16, timeout=60): sequence = 0 error_count = 0 packet_size = 128 - data = '\x00' * packet_size + data = b'\x00' * packet_size crc = self.calc_crc16(data) if crc_mode else self.calc_checksum(data) # Emit packet - if not self._send_packet(sequence, data, packet_size, crc_mode, crc, - error_count, retry, timeout): + if not self._send_packet( + sequence, data, packet_size, crc_mode, crc, + error_count, retry, timeout): log.error(error.ABORT_SEND_PACKET) # Already aborted return False @@ -127,7 +133,7 @@ def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1): ''' # Initiate protocol error_count = 0 - char = 0 + byte = 0 cancel = 0 sequence = 0 num_files = 0 @@ -137,21 +143,21 @@ def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1): self.abort(timeout=timeout) return None elif crc_mode and error_count < (retry / 2): - if not self.putc(CRC): + if not self.putc(const.CRC): time.sleep(delay) error_count += 1 else: crc_mode = 0 - if not self.putc(NAK): + if not self.putc(const.NAK): time.sleep(delay) error_count += 1 # or sent, waiting answer - char = self.getc(1, timeout) - if char is None: + byte = self.getc(1, timeout) + if byte is None: error_count += 1 continue - elif char == CAN: + elif byte == const.CAN: if cancel: log.error(error.ABORT_RECV_CAN_CAN) return None @@ -159,7 +165,7 @@ def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1): log.debug(error.DEBUG_RECV_CAN) cancel = 1 continue - elif char in [SOH, STX]: + elif byte in [const.SOH, const.STX]: break else: error_count += 1 @@ -170,59 +176,59 @@ def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1): while True: # Read next file in batch mode while True: - if char is None: + if byte is None: error_count += 1 - elif char == CAN: + elif byte == const.CAN: if cancel: log.error(error.ABORT_RECV_CAN_CAN) return None else: - log.debug(debug.DEBUG_RECV_CAN) + log.debug(error.DEBUG_RECV_CAN) cancel = 1 continue - elif char in [SOH, STX]: + elif byte in [const.SOH, const.STX]: seq1 = ord(self.getc(1)) seq2 = 0xff - ord(self.getc(1)) if seq1 == sequence and seq2 == sequence: - packet_size = 128 if char == SOH else 1024 + packet_size = 128 if byte == const.SOH else 1024 data = self.getc(packet_size + 1 + crc_mode) data = self._check_crc(data, crc_mode) if data: filename = data.split('\x00')[0] if not filename: # No filename, end of batch reception - self.putc(ACK) + self.putc(const.ACK) return num_files - log.info('Receiving %s to %s' % (filename, - basedir)) - fileout = open(os.path.join(basedir, - os.path.basename(filename)), 'wb') + log.info('Receiving %s to %s' % + (filename, basedir)) + fileout = open(os.path.join( + basedir, os.path.basename(filename)), 'wb') if not fileout: log.error(error.ABORT_OPEN_FILE) - self.putc(NAK) + self.putc(const.NAK) self.abort(timeout=timeout) return False else: - self.putc(ACK) + self.putc(const.ACK) break # Request retransmission if something went wrong self.getc(packet_size + 1 + crc_mode) - self.putc(NAK) + self.putc(const.NAK) self.getc(1, timeout) continue else: error_count += 1 self.getc(packet_size + 1 + crc_mode) - self.putc(NAK) + self.putc(const.NAK) self.getc(1, timeout) - stream_size = self._recv_stream(fileout, crc_mode, retry, timeout, - delay) + stream_size = self._recv_stream( + fileout, crc_mode, retry, timeout, delay) if not stream_size: log.error(error.ABORT_RECV_STREAM) @@ -234,5 +240,5 @@ def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1): sequence = 0 # Ask for the next sequence and receive the reply - self.putc(CRC) - char = self.getc(1, timeout) + self.putc(const.CRC) + byte = self.getc(1, timeout) From f805af0167978d6adc939b3c001cc91e7834e396 Mon Sep 17 00:00:00 2001 From: Jacob Christ Date: Fri, 12 Nov 2021 17:34:59 -0800 Subject: [PATCH 4/6] Fixed the progress bar so that it works with python 2.7 --- modem/protocol/xmodem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modem/protocol/xmodem.py b/modem/protocol/xmodem.py index b6a77e5..0e848af 100644 --- a/modem/protocol/xmodem.py +++ b/modem/protocol/xmodem.py @@ -230,8 +230,8 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): sequence = (sequence + 1) % 0x100 if filesize > 0: total_sent += packet_size - progress = total_sent/filesize - remain = (filesize - total_sent)/filesize + progress = float(total_sent)/float(filesize) + remain = float(filesize - total_sent)/filesize print(error.DEBUG_SEND_PROGRESS.format( int(50 * progress) * '=', progress * 100, From cf89f5555114b6a0f3bd6bc6ffeaefa52447066a Mon Sep 17 00:00:00 2001 From: Jacob Christ Date: Fri, 12 Nov 2021 19:48:22 -0800 Subject: [PATCH 5/6] Fixed confusing message that made it look like sending the EOT failed --- modem/error.py | 1 + modem/protocol/xmodem.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modem/error.py b/modem/error.py index 79dc726..ca4f066 100644 --- a/modem/error.py +++ b/modem/error.py @@ -25,6 +25,7 @@ DEBUG_START_FILENAME = _('Start sending "%s"') DEBUG_TRY_CRC = _('Try CRC mode') DEBUG_TRY_CHECKSUM = _('Try check sum mode') +DEBUG_SEND_EOT = _('Send ') DEBUG_FILENAME_SENT = _('File name {} sent') DEBUG_FILE_SENT = _('File {} sent') DEBUG_SEND_PROGRESS = _('Progress: |{}>{:3.0f}%{}|') diff --git a/modem/protocol/xmodem.py b/modem/protocol/xmodem.py index 0e848af..d5ea81f 100644 --- a/modem/protocol/xmodem.py +++ b/modem/protocol/xmodem.py @@ -242,7 +242,7 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): print() # STREAM FINISHED, SEND EOT - log.debug(error.ERROR_SEND_EOT) + log.error(error.DEBUG_SEND_EOT) if self._send_eot(error_count, retry, timeout): return True else: From 3c96e21541323947d13af3e853c45de98b6eab37 Mon Sep 17 00:00:00 2001 From: Jacob Christ Date: Sat, 13 Nov 2021 21:41:42 -0800 Subject: [PATCH 6/6] Added threading to support getting progress durring uploads. --- modem/protocol/xmodem.py | 26 +++++++++++++++++--------- modem/protocol/ymodem.py | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/modem/protocol/xmodem.py b/modem/protocol/xmodem.py index d5ea81f..aa0b93f 100644 --- a/modem/protocol/xmodem.py +++ b/modem/protocol/xmodem.py @@ -25,6 +25,14 @@ class XMODEM(Modem): # Protocol identifier protocol = const.PROTOCOL_XMODEM + def __init__(self, getc, putc): + Modem.__init__(self, getc, putc) + self.progress = 0 + return + + def get_progress(self): + return self.progress + def abort(self, count=2, timeout=60): ''' Send an abort sequence using CAN bytes. @@ -230,15 +238,15 @@ def _send_stream(self, stream, crc_mode, retry=16, timeout=0, filesize=0.0): sequence = (sequence + 1) % 0x100 if filesize > 0: total_sent += packet_size - progress = float(total_sent)/float(filesize) - remain = float(filesize - total_sent)/filesize - print(error.DEBUG_SEND_PROGRESS.format( - int(50 * progress) * '=', - progress * 100, - int(50 * remain) * ' ', - ), end='\r' - ) - sys.stdout.flush() + self.progress = float(total_sent)/float(filesize) + # remain = float(filesize - total_sent)/filesize + # print(error.DEBUG_SEND_PROGRESS.format( + # int(50 * self.progress) * '=', + # self.progress * 100, + # int(50 * remain) * ' ', + # ), end='\r' + # ) + # sys.stdout.flush() print() # STREAM FINISHED, SEND EOT diff --git a/modem/protocol/ymodem.py b/modem/protocol/ymodem.py index 0755cd0..4c930b8 100644 --- a/modem/protocol/ymodem.py +++ b/modem/protocol/ymodem.py @@ -1,6 +1,7 @@ import glob import os import time +from threading import Thread from modem import const from modem.tools import log from modem.protocol.xmodem import XMODEM @@ -15,6 +16,11 @@ class YMODEM(XMODEM): protocol = const.PROTOCOL_YMODEM + def __init__(self, getc, putc): + XMODEM.__init__(self, getc, putc) + self.thread = None + return + def send(self, pattern, retry=16, timeout=60): ''' Send one or more files via the YMODEM protocol. @@ -117,6 +123,20 @@ def send(self, pattern, retry=16, timeout=60): # All went fine return True + def send_threaded(self, pattern, retry=16, timeout=60): + if self.thread == None: + self.thread = Thread(target=self.send, args=(pattern, retry, timeout,)) + self.thread.daemon = True + self.thread.start() + return + + def send_join(self): + self.thread.join() + return + + def get_progress(self): + return XMODEM.get_progress(self) + def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1): ''' Receive some files via the YMODEM protocol and place them under