tools: Add telnet support to pyboard.py.
The adapter class "TelnetToSerial" is used to access the Telnet connection using the same API as with the serial connection. The function pyboard.run-test() has been removed to made the module generic and because this small test is no longer needed.
This commit is contained in:
parent
db109ca0fc
commit
cd14188bc8
@ -266,17 +266,19 @@ def run_tests(pyb, tests, args):
|
|||||||
def main():
|
def main():
|
||||||
cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.')
|
cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.')
|
||||||
cmd_parser.add_argument('--target', default='unix', help='the target platform')
|
cmd_parser.add_argument('--target', default='unix', help='the target platform')
|
||||||
cmd_parser.add_argument('--device', default='/dev/ttyACM0', help='the serial device of the target board')
|
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('-d', '--test-dirs', nargs='*', help='input test directories (if no files given)')
|
cmd_parser.add_argument('-d', '--test-dirs', nargs='*', help='input test directories (if no files given)')
|
||||||
cmd_parser.add_argument('--write-exp', action='store_true', help='save .exp files to run tests w/o CPython')
|
cmd_parser.add_argument('--write-exp', action='store_true', help='save .exp files to run tests w/o CPython')
|
||||||
cmd_parser.add_argument('--emit', default='bytecode', help='Micro Python emitter to use (bytecode or native)')
|
cmd_parser.add_argument('--emit', default='bytecode', help='Micro Python emitter to use (bytecode or native)')
|
||||||
cmd_parser.add_argument('-b', '--baudrate', default=115200, help='the baud rate of the serial device')
|
|
||||||
cmd_parser.add_argument('files', nargs='*', help='input test files')
|
cmd_parser.add_argument('files', nargs='*', help='input test files')
|
||||||
args = cmd_parser.parse_args()
|
args = cmd_parser.parse_args()
|
||||||
|
|
||||||
if args.target == 'pyboard' or args.target == 'wipy':
|
if args.target == 'pyboard' or args.target == 'wipy':
|
||||||
import pyboard
|
import pyboard
|
||||||
pyb = pyboard.Pyboard(args.device, args.baudrate)
|
pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password)
|
||||||
pyb.enter_raw_repl()
|
pyb.enter_raw_repl()
|
||||||
elif args.target == 'unix':
|
elif args.target == 'unix':
|
||||||
pyb = None
|
pyb = None
|
||||||
|
152
tools/pyboard.py
152
tools/pyboard.py
@ -10,6 +10,13 @@ Example usage:
|
|||||||
|
|
||||||
import pyboard
|
import pyboard
|
||||||
pyb = pyboard.Pyboard('/dev/ttyACM0')
|
pyb = pyboard.Pyboard('/dev/ttyACM0')
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
pyb = pyboard.Pyboard('192.168.1.1')
|
||||||
|
|
||||||
|
Then:
|
||||||
|
|
||||||
pyb.enter_raw_repl()
|
pyb.enter_raw_repl()
|
||||||
pyb.exec('pyb.LED(1).on()')
|
pyb.exec('pyb.LED(1).on()')
|
||||||
pyb.exit_raw_repl()
|
pyb.exit_raw_repl()
|
||||||
@ -31,7 +38,6 @@ Or:
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import serial
|
|
||||||
|
|
||||||
def stdout_write_bytes(b):
|
def stdout_write_bytes(b):
|
||||||
sys.stdout.buffer.write(b)
|
sys.stdout.buffer.write(b)
|
||||||
@ -40,9 +46,76 @@ def stdout_write_bytes(b):
|
|||||||
class PyboardError(BaseException):
|
class PyboardError(BaseException):
|
||||||
pass
|
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):
|
||||||
|
self.tn.write(bytes(user, 'ascii') + b"\r\n")
|
||||||
|
|
||||||
|
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):
|
||||||
|
# login succesful
|
||||||
|
from collections import deque
|
||||||
|
self.fifo = deque()
|
||||||
|
return
|
||||||
|
|
||||||
|
raise PyboardError('Failed to establish a telnet connection with the board')
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.tn.close()
|
||||||
|
except:
|
||||||
|
# the telnet object might not exist yet, so ignore this one
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read(self, size=1):
|
||||||
|
while len(self.fifo) < size:
|
||||||
|
timeout_count = 0
|
||||||
|
data = self.tn.read_eager()
|
||||||
|
if len(data):
|
||||||
|
self.fifo.extend(data)
|
||||||
|
timeout_count = 0
|
||||||
|
else:
|
||||||
|
time.sleep(0.25)
|
||||||
|
if self.read_timeout is not None and timeout_count > 4 * self.read_timeout:
|
||||||
|
break
|
||||||
|
timeout_count += 1
|
||||||
|
|
||||||
|
data = b''
|
||||||
|
while len(data) < size and len(self.fifo) > 0:
|
||||||
|
data += bytes([self.fifo.popleft()])
|
||||||
|
return data
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
self.tn.write(data)
|
||||||
|
return len(data)
|
||||||
|
|
||||||
|
def inWaiting(self):
|
||||||
|
n_waiting = len(self.fifo)
|
||||||
|
if not n_waiting:
|
||||||
|
data = self.tn.read_eager()
|
||||||
|
self.fifo.extend(data)
|
||||||
|
return len(data)
|
||||||
|
else:
|
||||||
|
return n_waiting
|
||||||
|
|
||||||
class Pyboard:
|
class Pyboard:
|
||||||
def __init__(self, serial_device, baudrate=115200):
|
def __init__(self, device, baudrate=115200, user='micro', password='python'):
|
||||||
self.serial = serial.Serial(serial_device, baudrate=baudrate, interCharTimeout=1)
|
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)
|
||||||
|
else:
|
||||||
|
import serial
|
||||||
|
self.serial = serial.Serial(device, baudrate=baudrate, interCharTimeout=1)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.serial.close()
|
self.serial.close()
|
||||||
@ -155,85 +228,28 @@ class Pyboard:
|
|||||||
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])
|
return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6])
|
||||||
|
|
||||||
def execfile(filename, device='/dev/ttyACM0'):
|
def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', password='python'):
|
||||||
pyb = Pyboard(device)
|
pyb = Pyboard(device, baudrate, user, password)
|
||||||
pyb.enter_raw_repl()
|
pyb.enter_raw_repl()
|
||||||
output = pyb.execfile(filename)
|
output = pyb.execfile(filename)
|
||||||
stdout_write_bytes(output)
|
stdout_write_bytes(output)
|
||||||
pyb.exit_raw_repl()
|
pyb.exit_raw_repl()
|
||||||
pyb.close()
|
pyb.close()
|
||||||
|
|
||||||
def run_test(device):
|
|
||||||
pyb = Pyboard(device)
|
|
||||||
pyb.enter_raw_repl()
|
|
||||||
print('opened device {}'.format(device))
|
|
||||||
|
|
||||||
pyb.exec('import pyb') # module pyb no longer imported by default, required for pyboard tests
|
|
||||||
print('seconds since boot:', pyb.get_time())
|
|
||||||
|
|
||||||
pyb.exec('def apply(l, f):\r\n for item in l:\r\n f(item)\r\n')
|
|
||||||
|
|
||||||
pyb.exec('leds=[pyb.LED(l) for l in range(1, 5)]')
|
|
||||||
pyb.exec('apply(leds, lambda l:l.off())')
|
|
||||||
|
|
||||||
## USR switch test
|
|
||||||
|
|
||||||
pyb.exec('switch = pyb.Switch()')
|
|
||||||
|
|
||||||
for i in range(2):
|
|
||||||
print("press USR button")
|
|
||||||
pyb.exec('while switch(): pyb.delay(10)')
|
|
||||||
pyb.exec('while not switch(): pyb.delay(10)')
|
|
||||||
|
|
||||||
print('USR switch passed')
|
|
||||||
|
|
||||||
## accel test
|
|
||||||
|
|
||||||
if True:
|
|
||||||
print("hold level")
|
|
||||||
pyb.exec('accel = pyb.Accel()')
|
|
||||||
pyb.exec('while abs(accel.x()) > 10 or abs(accel.y()) > 10: pyb.delay(10)')
|
|
||||||
|
|
||||||
print("tilt left")
|
|
||||||
pyb.exec('while accel.x() > -10: pyb.delay(10)')
|
|
||||||
pyb.exec('leds[0].on()')
|
|
||||||
|
|
||||||
print("tilt forward")
|
|
||||||
pyb.exec('while accel.y() < 10: pyb.delay(10)')
|
|
||||||
pyb.exec('leds[1].on()')
|
|
||||||
|
|
||||||
print("tilt right")
|
|
||||||
pyb.exec('while accel.x() < 10: pyb.delay(10)')
|
|
||||||
pyb.exec('leds[2].on()')
|
|
||||||
|
|
||||||
print("tilt backward")
|
|
||||||
pyb.exec('while accel.y() > -10: pyb.delay(10)')
|
|
||||||
pyb.exec('leds[3].on()')
|
|
||||||
|
|
||||||
print('accel passed')
|
|
||||||
|
|
||||||
print('seconds since boot:', pyb.get_time())
|
|
||||||
|
|
||||||
pyb.exec('apply(leds, lambda l:l.off())')
|
|
||||||
|
|
||||||
pyb.exit_raw_repl()
|
|
||||||
pyb.close()
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import argparse
|
import argparse
|
||||||
cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')
|
cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')
|
||||||
cmd_parser.add_argument('--device', default='/dev/ttyACM0', help='the serial device of 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('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]')
|
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('--test', action='store_true', help='run a small test suite on the pyboard')
|
|
||||||
cmd_parser.add_argument('files', nargs='*', help='input files')
|
cmd_parser.add_argument('files', nargs='*', help='input files')
|
||||||
args = cmd_parser.parse_args()
|
args = cmd_parser.parse_args()
|
||||||
|
|
||||||
if args.test:
|
|
||||||
run_test(device=args.device)
|
|
||||||
|
|
||||||
for filename in args.files:
|
for filename in args.files:
|
||||||
try:
|
try:
|
||||||
pyb = Pyboard(args.device)
|
pyb = Pyboard(args.device, args.baudrate, args.user, args.password)
|
||||||
pyb.enter_raw_repl()
|
pyb.enter_raw_repl()
|
||||||
with open(filename, 'rb') as f:
|
with open(filename, 'rb') as f:
|
||||||
pyfile = f.read()
|
pyfile = f.read()
|
||||||
@ -251,7 +267,7 @@ def main():
|
|||||||
|
|
||||||
if args.follow or len(args.files) == 0:
|
if args.follow or len(args.files) == 0:
|
||||||
try:
|
try:
|
||||||
pyb = Pyboard(args.device)
|
pyb = Pyboard(args.device, args.baudrate, args.user, args.password)
|
||||||
ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes)
|
ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes)
|
||||||
pyb.close()
|
pyb.close()
|
||||||
except PyboardError as er:
|
except PyboardError as er:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user