15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#!/usr/bin/env python 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Very simple serial terminal 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# (C)2002-2011 Chris Liechti <cliechti@gmx.net> 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Input characters are sent directly (only LF -> CR/LF/CRLF translation is 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# done), received characters are displayed as is (or escaped trough pythons 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# repr, useful for debug purposes) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import sys, os, serial, threading 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)try: 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) from serial.tools.list_ports import comports 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)except ImportError: 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) comports = None 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)EXITCHARCTER = serial.to_bytes([0x1d]) # GS/CTRL+] 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MENUCHARACTER = serial.to_bytes([0x14]) # Menu: CTRL+T 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DEFAULT_PORT = None 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DEFAULT_BAUDRATE = 9600 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DEFAULT_RTS = None 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DEFAULT_DTR = None 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def key_description(character): 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """generate a readable description for a key""" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ascii_code = ord(character) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ascii_code < 32: 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 'Ctrl+%c' % (ord('@') + ascii_code) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return repr(character) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# help text, starts with blank line! it's a function so that the current values 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# for the shortcut keys is used and not the value at program start 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def get_help_text(): 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return """ 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- pySerial (%(version)s) - miniterm - help 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(exit)-8s Exit program 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(menu)-8s Menu escape key, followed by: 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- Menu keys: 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(itself)-7s Send the menu character itself to remote 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(exchar)-7s Send the exit character itself to remote 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(info)-7s Show info 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(upload)-7s Upload file (prompt will be shown) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- Toggles: 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(rts)-7s RTS %(echo)-7s local echo 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(dtr)-7s DTR %(break)-7s BREAK 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- %(lfm)-7s line feed %(repr)-7s Cycle repr mode 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- Port settings (%(menu)s followed by the following): 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- p change port 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- 7 8 set data bits 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- n e o s m change parity (None, Even, Odd, Space, Mark) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- 1 2 3 set stop bits (1, 2, 1.5) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- b change baud rate 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- x X disable/enable software flow control 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--- r R disable/enable hardware flow control 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""" % { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'version': getattr(serial, 'VERSION', 'unknown version'), 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'exit': key_description(EXITCHARCTER), 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'menu': key_description(MENUCHARACTER), 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'rts': key_description('\x12'), 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'repr': key_description('\x01'), 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'dtr': key_description('\x04'), 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'lfm': key_description('\x0c'), 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'break': key_description('\x02'), 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'echo': key_description('\x05'), 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'info': key_description('\x09'), 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'upload': key_description('\x15'), 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'itself': key_description(MENUCHARACTER), 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'exchar': key_description(EXITCHARCTER), 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if sys.version_info >= (3, 0): 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def character(b): 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return b.decode('latin1') 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else: 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def character(b): 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return b 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)LF = serial.to_bytes([10]) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CR = serial.to_bytes([13]) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CRLF = serial.to_bytes([13, 10]) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)X00 = serial.to_bytes([0]) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)X0E = serial.to_bytes([0x0e]) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# first choose a platform dependant way to read single characters from the console 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)global console 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if os.name == 'nt': 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import msvcrt 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) class Console(object): 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def __init__(self): 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pass 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def setup(self): 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pass # Do nothing for 'nt' 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def cleanup(self): 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pass # Do nothing for 'nt' 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def getkey(self): 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while True: 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) z = msvcrt.getch() 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if z == X00 or z == X0E: # functions keys, ignore 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) msvcrt.getch() 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if z == CR: 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return LF 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return z 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console = Console() 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)elif os.name == 'posix': 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import termios, sys, os 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) class Console(object): 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def __init__(self): 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.fd = sys.stdin.fileno() 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.old = None 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def setup(self): 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.old = termios.tcgetattr(self.fd) 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new = termios.tcgetattr(self.fd) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new[3] = new[3] & ~termios.ICANON & ~termios.ECHO & ~termios.ISIG 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new[6][termios.VMIN] = 1 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new[6][termios.VTIME] = 0 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) termios.tcsetattr(self.fd, termios.TCSANOW, new) 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def getkey(self): 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) c = os.read(self.fd, 1) 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return c 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def cleanup(self): 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.old is not None: 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console = Console() 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def cleanup_console(): 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.cleanup() 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.exitfunc = cleanup_console # terminal modes have to be restored on exit... 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else: 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raise NotImplementedError("Sorry no implementation for your platform (%s) available." % sys.platform) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def dump_port_list(): 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if comports: 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('\n--- Available ports:\n') 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for port, desc, hwid in sorted(comports()): 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) #~ sys.stderr.write('--- %-20s %s [%s]\n' % (port, desc, hwid)) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- %-20s %s\n' % (port, desc)) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CONVERT_CRLF = 2 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CONVERT_CR = 1 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CONVERT_LF = 0 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NEWLINE_CONVERISON_MAP = (LF, CR, CRLF) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)LF_MODES = ('LF', 'CR', 'CR/LF') 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)REPR_MODES = ('raw', 'some control', 'all control', 'hex') 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Miniterm(object): 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def __init__(self, port, baudrate, parity, rtscts, xonxoff, echo=False, convert_outgoing=CONVERT_CRLF, repr_mode=0): 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial = serial.serial_for_url(port, baudrate, parity=parity, rtscts=rtscts, xonxoff=xonxoff, timeout=1) 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except AttributeError: 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # happens when the installed pyserial is older than 2.5. use the 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Serial class directly then. 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial = serial.Serial(port, baudrate, parity=parity, rtscts=rtscts, xonxoff=xonxoff, timeout=1) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.echo = echo 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.repr_mode = repr_mode 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.convert_outgoing = convert_outgoing 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.newline = NEWLINE_CONVERISON_MAP[self.convert_outgoing] 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dtr_state = True 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.rts_state = True 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.break_state = False 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def _start_reader(self): 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Start reader thread""" 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._reader_alive = True 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # start serial->console thread 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.receiver_thread = threading.Thread(target=self.reader) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.receiver_thread.setDaemon(True) 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.receiver_thread.start() 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def _stop_reader(self): 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Stop reader thread only, wait for clean exit of thread""" 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._reader_alive = False 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.receiver_thread.join() 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def start(self): 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.alive = True 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._start_reader() 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # enter console->serial loop 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.transmitter_thread = threading.Thread(target=self.writer) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.transmitter_thread.setDaemon(True) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.transmitter_thread.start() 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def stop(self): 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.alive = False 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def join(self, transmit_only=False): 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.transmitter_thread.join() 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not transmit_only: 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.receiver_thread.join() 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def dump_port_settings(self): 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write("\n--- Settings: %s %s,%s,%s,%s\n" % ( 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.portstr, 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.baudrate, 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.bytesize, 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.parity, 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.stopbits)) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- RTS: %-8s DTR: %-8s BREAK: %-8s\n' % ( 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.rts_state and 'active' or 'inactive'), 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.dtr_state and 'active' or 'inactive'), 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.break_state and 'active' or 'inactive'))) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- CTS: %-8s DSR: %-8s RI: %-8s CD: %-8s\n' % ( 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.serial.getCTS() and 'active' or 'inactive'), 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.serial.getDSR() and 'active' or 'inactive'), 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.serial.getRI() and 'active' or 'inactive'), 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (self.serial.getCD() and 'active' or 'inactive'))) 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except serial.SerialException: 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # on RFC 2217 ports it can happen to no modem state notification was 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # yet received. ignore this error. 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pass 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- software flow control: %s\n' % (self.serial.xonxoff and 'active' or 'inactive')) 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- hardware flow control: %s\n' % (self.serial.rtscts and 'active' or 'inactive')) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- data escaping: %s linefeed: %s\n' % ( 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) REPR_MODES[self.repr_mode], 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LF_MODES[self.convert_outgoing])) 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def reader(self): 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """loop and copy serial->console""" 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while self.alive and self._reader_alive: 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data = character(self.serial.read(1)) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.repr_mode == 0: 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # direct output, just have to care about newline setting 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if data == '\r' and self.convert_outgoing == CONVERT_CR: 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write('\n') 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write(data) 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif self.repr_mode == 1: 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # escape non-printable, let pass newlines 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.convert_outgoing == CONVERT_CRLF and data in '\r\n': 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if data == '\n': 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write('\n') 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif data == '\r': 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pass 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif data == '\n' and self.convert_outgoing == CONVERT_LF: 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write('\n') 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif data == '\r' and self.convert_outgoing == CONVERT_CR: 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write('\n') 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write(repr(data)[1:-1]) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif self.repr_mode == 2: 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # escape all non-printable, including newline 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write(repr(data)[1:-1]) 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif self.repr_mode == 3: 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # escape everything (hexdump) 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for c in data: 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write("%s " % c.encode('hex')) 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.flush() 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except serial.SerialException, e: 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.alive = False 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # would be nice if the console reader could be interruptted at this 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # point... 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raise 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def writer(self): 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """\ 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Loop and copy console->serial until EXITCHARCTER character is 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) found. When MENUCHARACTER is found, interpret the next key 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) locally. 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) menu_active = False 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while self.alive: 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) b = console.getkey() 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except KeyboardInterrupt: 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) b = serial.to_bytes([3]) 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) c = character(b) 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if menu_active: 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if c == MENUCHARACTER or c == EXITCHARCTER: # Menu character again/exit char -> send itself 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.write(b) # send character 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.echo: 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write(c) 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x15': # CTRL+U -> upload file 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('\n--- File to upload: ') 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.flush() 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.cleanup() 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) filename = sys.stdin.readline().rstrip('\r\n') 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if filename: 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file = open(filename, 'r') 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- Sending file %s ---\n' % filename) 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while True: 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) line = file.readline().rstrip('\r\n') 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not line: 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.write(line) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.write('\r\n') 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Wait for output buffer to drain. 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.flush() 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('.') # Progress indicator. 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('\n--- File %s sent ---\n' % filename) 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except IOError, e: 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- ERROR opening file %s: %s ---\n' % (filename, e)) 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.setup() 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in '\x08hH?': # CTRL+H, h, H, ? -> Show help 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write(get_help_text()) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x12': # CTRL+R -> Toggle RTS 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.rts_state = not self.rts_state 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.setRTS(self.rts_state) 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- RTS %s ---\n' % (self.rts_state and 'active' or 'inactive')) 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x04': # CTRL+D -> Toggle DTR 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dtr_state = not self.dtr_state 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.setDTR(self.dtr_state) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- DTR %s ---\n' % (self.dtr_state and 'active' or 'inactive')) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x02': # CTRL+B -> toggle BREAK condition 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.break_state = not self.break_state 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.setBreak(self.break_state) 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- BREAK %s ---\n' % (self.break_state and 'active' or 'inactive')) 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x05': # CTRL+E -> toggle local echo 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.echo = not self.echo 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- local echo %s ---\n' % (self.echo and 'active' or 'inactive')) 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x09': # CTRL+I -> info 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x01': # CTRL+A -> cycle escape mode 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.repr_mode += 1 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.repr_mode > 3: 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.repr_mode = 0 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- escape data: %s ---\n' % ( 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) REPR_MODES[self.repr_mode], 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) )) 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\x0c': # CTRL+L -> cycle linefeed mode 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.convert_outgoing += 1 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.convert_outgoing > 2: 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.convert_outgoing = 0 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.newline = NEWLINE_CONVERISON_MAP[self.convert_outgoing] 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- line feed %s ---\n' % ( 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LF_MODES[self.convert_outgoing], 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) )) 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'pP': # P -> change port 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dump_port_list() 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- Enter port name: ') 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.flush() 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.cleanup() 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) port = sys.stdin.readline().strip() 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except KeyboardInterrupt: 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) port = None 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.setup() 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if port and port != self.serial.port: 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # reader thread needs to be shut down 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._stop_reader() 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # save settings 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) settings = self.serial.getSettingsDict() 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial = serial.serial_for_url(port, do_not_open=True) 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except AttributeError: 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # happens when the installed pyserial is older than 2.5. use the 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Serial class directly then. 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial = serial.Serial() 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.port = port 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # restore settings and open 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.applySettingsDict(settings) 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.open() 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.setRTS(self.rts_state) 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.setDTR(self.dtr_state) 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.setBreak(self.break_state) 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except Exception, e: 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- ERROR opening new port: %s ---\n' % (e,)) 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_serial.close() 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.close() 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial = new_serial 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- Port changed to: %s ---\n' % (self.serial.port,)) 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # and restart the reader thread 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._start_reader() 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'bB': # B -> change baudrate 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('\n--- Baudrate: ') 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.flush() 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.cleanup() 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) backup = self.serial.baudrate 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.baudrate = int(sys.stdin.readline().strip()) 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except ValueError, e: 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- ERROR setting baudrate: %s ---\n' % (e,)) 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.baudrate = backup 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.setup() 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '8': # 8 -> change to 8 bits 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.bytesize = serial.EIGHTBITS 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '7': # 7 -> change to 8 bits 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.bytesize = serial.SEVENBITS 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'eE': # E -> change to even parity 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.parity = serial.PARITY_EVEN 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'oO': # O -> change to odd parity 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.parity = serial.PARITY_ODD 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'mM': # M -> change to mark parity 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.parity = serial.PARITY_MARK 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'sS': # S -> change to space parity 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.parity = serial.PARITY_SPACE 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'nN': # N -> change to no parity 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.parity = serial.PARITY_NONE 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '1': # 1 -> change to 1 stop bits 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.stopbits = serial.STOPBITS_ONE 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '2': # 2 -> change to 2 stop bits 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.stopbits = serial.STOPBITS_TWO 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '3': # 3 -> change to 1.5 stop bits 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.stopbits = serial.STOPBITS_ONE_POINT_FIVE 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'xX': # X -> change software flow control 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.xonxoff = (c == 'X') 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c in 'rR': # R -> change hardware flow control 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.rtscts = (c == 'R') 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.dump_port_settings() 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- unknown menu character %s --\n' % key_description(c)) 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) menu_active = False 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == MENUCHARACTER: # next char will be for menu 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) menu_active = True 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == EXITCHARCTER: 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.stop() 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break # exit app 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c == '\n': 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.write(self.newline) # send newline character(s) 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.echo: 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write(c) # local echo is a real newline in any case 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.flush() 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.serial.write(b) # send byte 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.echo: 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.write(c) 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stdout.flush() 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except: 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.alive = False 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raise 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def main(): 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import optparse 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser = optparse.OptionParser( 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) usage = "%prog [options] [port [baudrate]]", 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) description = "Miniterm - A simple terminal program for the serial port." 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group = optparse.OptionGroup(parser, "Port settings") 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("-p", "--port", 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "port", 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "port, a number or a device name. (deprecated option, use parameter instead)", 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = DEFAULT_PORT 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("-b", "--baud", 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "baudrate", 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store", 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) type = 'int', 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "set baud rate, default %default", 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = DEFAULT_BAUDRATE 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--parity", 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "parity", 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store", 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "set parity, one of [N, E, O, S, M], default=N", 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = 'N' 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--rtscts", 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "rtscts", 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store_true", 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "enable RTS/CTS flow control (default off)", 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = False 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--xonxoff", 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "xonxoff", 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store_true", 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "enable software flow control (default off)", 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = False 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--rts", 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "rts_state", 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store", 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) type = 'int', 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "set initial RTS line state (possible values: 0, 1)", 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = DEFAULT_RTS 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--dtr", 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "dtr_state", 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store", 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) type = 'int', 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "set initial DTR line state (possible values: 0, 1)", 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = DEFAULT_DTR 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.add_option_group(group) 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group = optparse.OptionGroup(parser, "Data handling") 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("-e", "--echo", 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "echo", 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store_true", 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "enable local echo (default off)", 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = False 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--cr", 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "cr", 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store_true", 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "do not send CR+LF, send CR only", 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = False 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--lf", 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "lf", 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store_true", 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "do not send CR+LF, send LF only", 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = False 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("-D", "--debug", 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "repr_mode", 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "count", 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = """debug received data (escape non-printable chars) 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)--debug can be given multiple times: 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)0: just print what is received 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)1: escape non-printable characters, do newlines as unusual 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)2: escape non-printable characters, newlines too 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)3: hex dump everything""", 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = 0 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.add_option_group(group) 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group = optparse.OptionGroup(parser, "Hotkeys") 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--exit-char", 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "exit_char", 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store", 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) type = 'int', 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "ASCII code of special character that is used to exit the application", 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = 0x1d 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("--menu-char", 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "menu_char", 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store", 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) type = 'int', 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "ASCII code of special character that is used to control miniterm (menu)", 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = 0x14 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.add_option_group(group) 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group = optparse.OptionGroup(parser, "Diagnostics") 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) group.add_option("-q", "--quiet", 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest = "quiet", 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action = "store_true", 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help = "suppress non-error messages", 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default = False 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.add_option_group(group) 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (options, args) = parser.parse_args() 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.parity = options.parity.upper() 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.parity not in 'NEOSM': 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.error("invalid parity") 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.cr and options.lf: 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.error("only one of --cr or --lf can be specified") 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.menu_char == options.exit_char: 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.error('--exit-char can not be the same as --menu-char') 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) global EXITCHARCTER, MENUCHARACTER 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXITCHARCTER = chr(options.exit_char) 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MENUCHARACTER = chr(options.menu_char) 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) port = options.port 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) baudrate = options.baudrate 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if args: 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.port is not None: 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.error("no arguments are allowed, options only when --port is given") 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) port = args.pop(0) 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if args: 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) baudrate = int(args[0]) 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except ValueError: 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.error("baud rate must be a number, not %r" % args[0]) 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args.pop(0) 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if args: 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.error("too many arguments") 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # noport given on command line -> ask user now 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if port is None: 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dump_port_list() 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) port = raw_input('Enter port name:') 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) convert_outgoing = CONVERT_CRLF 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.cr: 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) convert_outgoing = CONVERT_CR 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif options.lf: 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) convert_outgoing = CONVERT_LF 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm = Miniterm( 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) port, 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) baudrate, 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) options.parity, 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rtscts=options.rtscts, 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) xonxoff=options.xonxoff, 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) echo=options.echo, 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) convert_outgoing=convert_outgoing, 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) repr_mode=options.repr_mode, 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ) 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except serial.SerialException, e: 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write("could not open port %r: %s\n" % (port, e)) 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.exit(1) 6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not options.quiet: 6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- Miniterm on %s: %d,%s,%s,%s ---\n' % ( 6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.portstr, 6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.baudrate, 6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.bytesize, 6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.parity, 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.stopbits, 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) )) 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- Quit: %s | Menu: %s | Help: %s followed by %s ---\n' % ( 6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_description(EXITCHARCTER), 6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_description(MENUCHARACTER), 6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_description(MENUCHARACTER), 6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_description('\x08'), 6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) )) 6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.dtr_state is not None: 6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not options.quiet: 6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- forcing DTR %s\n' % (options.dtr_state and 'active' or 'inactive')) 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.setDTR(options.dtr_state) 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.dtr_state = options.dtr_state 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.rts_state is not None: 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not options.quiet: 6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write('--- forcing RTS %s\n' % (options.rts_state and 'active' or 'inactive')) 6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.serial.setRTS(options.rts_state) 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.rts_state = options.rts_state 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.setup() 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.start() 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.join(True) 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except KeyboardInterrupt: 6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pass 6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not options.quiet: 6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sys.stderr.write("\n--- exit ---\n") 6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) miniterm.join() 6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) #~ console.cleanup() 6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if __name__ == '__main__': 6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) main() 695