From d02e2f78069a6718dda17b5f4197175e64e4d4e9 Mon Sep 17 00:00:00 2001 From: Big Circle <794557226@qq.com> Date: Wed, 15 Jan 2020 11:28:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=5F=5Fversion=5F=5F.py?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E7=94=A8=E6=9D=A5=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=EF=BC=8C=E5=BD=93=E5=89=8D=E7=89=88?= =?UTF-8?q?=E6=9C=AC1.1.2=EF=BC=9B=20=E4=BF=AE=E6=94=B9=E8=8E=B7=E5=BE=97?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E5=87=BD=E6=95=B0=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E5=9C=A8=E5=85=B6=E4=BB=96=E7=A8=8B=E5=BA=8F=E4=B8=AD?= =?UTF-8?q?=E8=B0=83=E7=94=A8=EF=BC=9B=20=E5=B0=86enter=5Fraw=5Frepl?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=8B=86=E5=88=86=E5=87=BA=E4=B8=80=E4=B8=AA?= =?UTF-8?q?enter=5Fraw=5Frepl=5Fnot=5Freset=E5=87=BD=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=9C=A8=E4=B8=80=E4=BA=9B=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E4=B8=AD=E5=8A=A0=E5=BF=AB=E7=A8=8B=E5=BA=8F=E9=80=9F=E5=BA=A6?= =?UTF-8?q?=EF=BC=9B=20=E4=BF=AE=E6=94=B9setup.py=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E6=8C=87=E5=AE=9A=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=EF=BC=8C=E5=B9=B6=E4=B8=BAgit=E5=BA=93=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8A=A0=E6=A0=87=E7=AD=BE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ampy/__version__.py | 4 ++ ampy/files.py | 7 ++- ampy/pyboard.py | 139 +++++++++++++++++++++++++++++++------------- setup.py | 13 +++-- 4 files changed, 116 insertions(+), 47 deletions(-) create mode 100644 ampy/__version__.py diff --git a/ampy/__version__.py b/ampy/__version__.py new file mode 100644 index 0000000..9cbca53 --- /dev/null +++ b/ampy/__version__.py @@ -0,0 +1,4 @@ + +VERSION = (1, 1, 2) + +__version__ = '.'.join(map(str, VERSION)) diff --git a/ampy/files.py b/ampy/files.py index 725a290..062b3d4 100644 --- a/ampy/files.py +++ b/ampy/files.py @@ -319,11 +319,12 @@ def version(self): import wonderbits print(wonderbits.__version__) """ - self._pyboard.enter_raw_repl() + self._pyboard.enter_raw_repl_not_rest() out = None try: - out = self._pyboard.exec_(textwrap.dedent(command)).replace("\n", "").replace("\r", "") + out = self._pyboard.exec_(textwrap.dedent(command)).decode("utf-8") + out = out.replace("\n", "").replace("\r", "") except PyboardError as ex: raise ex self._pyboard.exit_raw_repl() - return out.decode("utf-8") + return out diff --git a/ampy/pyboard.py b/ampy/pyboard.py index 52eac53..e88815c 100644 --- a/ampy/pyboard.py +++ b/ampy/pyboard.py @@ -1,5 +1,4 @@ #!/usr/bin/env python - """ pyboard interface @@ -48,34 +47,42 @@ # Python2 doesn't have buffer attr stdout = sys.stdout + def stdout_write_bytes(b): b = b.replace(b"\x04", b"") stdout.write(b) stdout.flush() + class PyboardError(BaseException): pass + class TelnetToSerial: def __init__(self, ip, user, password, read_timeout=None): import telnetlib self.tn = telnetlib.Telnet(ip, timeout=15) self.read_timeout = read_timeout - if b'Login as:' in self.tn.read_until(b'Login as:', timeout=read_timeout): + if b'Login as:' in self.tn.read_until( + b'Login as:', timeout=read_timeout): self.tn.write(bytes(user, 'ascii') + b"\r\n") - if b'Password:' in self.tn.read_until(b'Password:', timeout=read_timeout): + if b'Password:' in self.tn.read_until( + b'Password:', timeout=read_timeout): # needed because of internal implementation details of the telnet server time.sleep(0.2) self.tn.write(bytes(password, 'ascii') + b"\r\n") - if b'for more information.' in self.tn.read_until(b'Type "help()" for more information.', timeout=read_timeout): + if b'for more information.' in self.tn.read_until( + b'Type "help()" for more information.', + timeout=read_timeout): # login succesful from collections import deque self.fifo = deque() return - raise PyboardError('Failed to establish a telnet connection with the board') + raise PyboardError( + 'Failed to establish a telnet connection with the board') def __del__(self): self.close() @@ -118,26 +125,38 @@ def inWaiting(self): else: return n_waiting + class Pyboard: - def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0, rawdelay=0): + def __init__(self, + device, + baudrate=115200, + user='micro', + password='python', + wait=0, + rawdelay=0): global _rawdelay _rawdelay = rawdelay - if device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3: + if device and device[0].isdigit() and device[-1].isdigit( + ) and device.count('.') == 3: # device looks like an IP address - self.serial = TelnetToSerial(device, user, password, read_timeout=10) + self.serial = TelnetToSerial( + device, user, password, read_timeout=10) else: import serial delayed = False for attempt in range(wait + 1): try: - self.serial = serial.Serial(device, baudrate=baudrate, interCharTimeout=1) + self.serial = serial.Serial( + device, baudrate=baudrate, interCharTimeout=1) break - except (OSError, IOError) as e: # Py2 and Py3 have different errors + except (OSError, + IOError) as e: # Py2 and Py3 have different errors # print(e) if wait == 0: continue if attempt == 0: - sys.stdout.write('Waiting {} seconds for pyboard '.format(wait)) + sys.stdout.write( + 'Waiting {} seconds for pyboard '.format(wait)) delayed = True time.sleep(1) sys.stdout.write('.') @@ -152,7 +171,8 @@ def __init__(self, device, baudrate=115200, user='micro', password='python', wai def close(self): self.serial.close() - def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): + def read_until(self, min_num_bytes, ending, timeout=10, + data_consumer=None): data = self.serial.read(min_num_bytes) if data_consumer: data_consumer(data) @@ -173,8 +193,7 @@ def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): time.sleep(0.01) return data - def enter_raw_repl(self): - # Brief delay before sending RAW MODE char if requests + def enter_raw_repl_not_rest(self): if _rawdelay > 0: time.sleep(_rawdelay) @@ -190,13 +209,16 @@ def enter_raw_repl(self): self.serial.read(n) n = self.serial.inWaiting() - self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL - data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n>') - if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'): + self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL + data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n') + if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'): print(data) raise PyboardError('could not enter raw repl') - self.serial.write(b'\x04') # ctrl-D: soft reset + def enter_raw_repl(self): + # Brief delay before sending RAW MODE char if requests + self.enter_raw_repl_not_rest() + self.serial.write(b'\x04') # ctrl-D: soft reset data = self.read_until(1, b'soft reboot\r\n') if not data.endswith(b'soft reboot\r\n'): print(data) @@ -206,10 +228,10 @@ def enter_raw_repl(self): # Modification from original pyboard.py below: # Add a small delay and send Ctrl-C twice after soft reboot to ensure # any main program loop in main.py is interrupted. - time.sleep(0.5) - self.serial.write(b'\x03') - time.sleep(0.1) # (slight delay before second interrupt - self.serial.write(b'\x03') + # time.sleep(0.5) + # self.serial.write(b'\x03') + # time.sleep(0.1) # (slight delay before second interrupt + # self.serial.write(b'\x03') # End modification above. data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n') if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'): @@ -217,11 +239,12 @@ def enter_raw_repl(self): raise PyboardError('could not enter raw repl') def exit_raw_repl(self): - self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL + self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL def follow(self, timeout, data_consumer=None): # wait for normal output - data = self.read_until(1, b'\x04', timeout=timeout, data_consumer=data_consumer) + data = self.read_until( + 1, b'\x04', timeout=timeout, data_consumer=data_consumer) if not data.endswith(b'\x04'): raise PyboardError('timeout waiting for first EOF reception') data = data[:-1] @@ -248,7 +271,8 @@ def exec_raw_no_follow(self, command): # write command for i in range(0, len(command_bytes), 256): - self.serial.write(command_bytes[i:min(i + 256, len(command_bytes))]) + self.serial.write( + command_bytes[i:min(i + 256, len(command_bytes))]) time.sleep(0.01) self.serial.write(b'\x04') @@ -258,7 +282,7 @@ def exec_raw_no_follow(self, command): raise PyboardError('could not exec command') def exec_raw(self, command, timeout=10, data_consumer=None): - self.exec_raw_no_follow(command); + self.exec_raw_no_follow(command) return self.follow(timeout, data_consumer) def eval(self, expression): @@ -278,14 +302,22 @@ def execfile(self, filename): return self.exec_(pyfile) def get_time(self): - t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ') + t = str( + self.eval('pyb.RTC().datetime()'), + encoding='utf8')[1:-1].split(', ') return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6]) + # in Python2 exec is a keyword so one must use "exec_" # but for Python3 we want to provide the nicer version "exec" setattr(Pyboard, "exec", Pyboard.exec_) -def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', password='python'): + +def execfile(filename, + device='/dev/ttyACM0', + baudrate=115200, + user='micro', + password='python'): pyb = Pyboard(device, baudrate, user, password) pyb.enter_raw_repl() output = pyb.execfile(filename) @@ -293,24 +325,48 @@ def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', pas pyb.exit_raw_repl() pyb.close() + def main(): import argparse - cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.') - cmd_parser.add_argument('--device', default='/dev/ttyACM0', help='the serial device or the IP address of the pyboard') - cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device') - cmd_parser.add_argument('-u', '--user', default='micro', help='the telnet login username') - cmd_parser.add_argument('-p', '--password', default='python', help='the telnet login password') - cmd_parser.add_argument('-c', '--command', help='program passed in as string') - cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available') - cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]') + cmd_parser = argparse.ArgumentParser( + description='Run scripts on the pyboard.') + cmd_parser.add_argument( + '--device', + default='/dev/ttyACM0', + help='the serial device or the IP address of the pyboard') + cmd_parser.add_argument( + '-b', + '--baudrate', + default=115200, + help='the baud rate of the serial device') + cmd_parser.add_argument( + '-u', '--user', default='micro', help='the telnet login username') + cmd_parser.add_argument( + '-p', '--password', default='python', help='the telnet login password') + cmd_parser.add_argument( + '-c', '--command', help='program passed in as string') + cmd_parser.add_argument( + '-w', + '--wait', + default=0, + type=int, + help='seconds to wait for USB connected board to become available') + cmd_parser.add_argument( + '--follow', + action='store_true', + help= + 'follow the output after running the scripts [default if no scripts given]' + ) cmd_parser.add_argument('files', nargs='*', help='input files') args = cmd_parser.parse_args() def execbuffer(buf): try: - pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait) + pyb = Pyboard(args.device, args.baudrate, args.user, args.password, + args.wait) pyb.enter_raw_repl() - ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes) + ret, ret_err = pyb.exec_raw( + buf, timeout=None, data_consumer=stdout_write_bytes) pyb.exit_raw_repl() pyb.close() except PyboardError as er: @@ -332,8 +388,10 @@ def execbuffer(buf): if args.follow or (args.command is None and len(args.files) == 0): try: - pyb = Pyboard(args.device, args.baudrate, args.user, args.password, args.wait) - ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes) + pyb = Pyboard(args.device, args.baudrate, args.user, args.password, + args.wait) + ret, ret_err = pyb.follow( + timeout=None, data_consumer=stdout_write_bytes) pyb.close() except PyboardError as er: print(er) @@ -344,5 +402,6 @@ def execbuffer(buf): stdout_write_bytes(ret_err) sys.exit(1) + if __name__ == "__main__": main() diff --git a/setup.py b/setup.py index 5885f1d..be564df 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,11 @@ with open(path.join(here, 'README.md'), encoding='utf-8') as f: long_description = f.read() +about = {} + +with open(os.path.join(here, 'ampy', '__version__.py')) as f: + exec(f.read(), about) + class UploadCommand(Command): """Support setup.py upload.""" @@ -66,15 +71,15 @@ def run(self): os.system('twine upload dist/*') # self.status('Pushing git tagsā€¦') - # os.system('git tag v{0}'.format(about['__version__'])) - # os.system('git push --tags') + os.system('git tag v{0}'.format(about['__version__'])) + os.system('git push --tags') sys.exit() setup( name='wonderbits-ampy', - # version = '1.0.0', - use_scm_version=True, + version = about['__version__'], + # use_scm_version=True, setup_requires=['setuptools_scm'], description='ampy (Adafruit MicroPython tool) is a command line tool to interact with a CircuitPython or MicroPython board over a serial connection.',