| 
									
										
										
										
											2017-06-27 20:23:30 -04:00
										 |  |  | #!/usr/bin/env python2 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | # Script to implement a test console with firmware over serial port | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											2021-02-18 14:01:40 -05:00
										 |  |  | # Copyright (C) 2016-2021  Kevin O'Connor <kevin@koconnor.net> | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # This file may be distributed under the terms of the GNU GPLv3 license. | 
					
						
							|  |  |  | import sys, optparse, os, re, logging | 
					
						
							| 
									
										
										
										
											2023-01-07 11:53:09 -05:00
										 |  |  | import util, reactor, serialhdl, msgproto, clocksync | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  | help_txt = """
 | 
					
						
							|  |  |  |   This is a debugging console for the Klipper micro-controller. | 
					
						
							|  |  |  |   In addition to mcu commands, the following artificial commands are | 
					
						
							|  |  |  |   available: | 
					
						
							|  |  |  |     DELAY : Send a command at a clock time (eg, "DELAY 9999 get_uptime") | 
					
						
							| 
									
										
										
										
											2017-09-06 15:40:23 -04:00
										 |  |  |     FLOOD : Send a command many times (eg, "FLOOD 22 .01 get_uptime") | 
					
						
							| 
									
										
										
										
											2018-11-16 17:16:14 -05:00
										 |  |  |     SUPPRESS : Suppress a response message (eg, "SUPPRESS analog_in_state 4") | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |     SET   : Create a local variable (eg, "SET myvar 123.4") | 
					
						
							| 
									
										
										
										
											2022-07-29 13:30:39 -04:00
										 |  |  |     DUMP  : Dump memory (eg, "DUMP 0x12345678 100 32") | 
					
						
							|  |  |  |     FILEDUMP : Dump to file (eg, "FILEDUMP data.bin 0x12345678 100 32") | 
					
						
							| 
									
										
										
										
											2017-08-07 20:49:42 -04:00
										 |  |  |     STATS : Report serial statistics | 
					
						
							| 
									
										
										
										
											2017-08-07 20:40:32 -04:00
										 |  |  |     LIST  : List available mcu commands, local commands, and local variables | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |     HELP  : Show this text | 
					
						
							|  |  |  |   All commands also support evaluation by enclosing an expression in { }. | 
					
						
							|  |  |  |   For example, "reset_step_clock oid=4 clock={clock + freq}".  In addition | 
					
						
							|  |  |  |   to user defined variables (via the SET command) the following builtin | 
					
						
							|  |  |  |   variables may be used in expressions: | 
					
						
							|  |  |  |     clock : The current mcu clock time (as estimated by the host) | 
					
						
							|  |  |  |     freq  : The mcu clock frequency | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | re_eval = re.compile(r'\{(?P<eval>[^}]*)\}') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class KeyboardReader: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:13:15 -05:00
										 |  |  |     def __init__(self, reactor, serialport, baud, canbus_iface, canbus_nodeid): | 
					
						
							| 
									
										
										
										
											2021-01-30 00:01:23 -05:00
										 |  |  |         self.serialport = serialport | 
					
						
							|  |  |  |         self.baud = baud | 
					
						
							| 
									
										
										
										
											2021-02-07 17:13:15 -05:00
										 |  |  |         self.canbus_iface = canbus_iface | 
					
						
							|  |  |  |         self.canbus_nodeid = canbus_nodeid | 
					
						
							| 
									
										
										
										
											2021-01-30 00:01:23 -05:00
										 |  |  |         self.ser = serialhdl.SerialReader(reactor) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |         self.reactor = reactor | 
					
						
							| 
									
										
										
										
											2018-05-16 09:27:50 -04:00
										 |  |  |         self.start_time = reactor.monotonic() | 
					
						
							| 
									
										
										
										
											2017-09-18 21:41:00 -04:00
										 |  |  |         self.clocksync = clocksync.ClockSync(self.reactor) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |         self.fd = sys.stdin.fileno() | 
					
						
							|  |  |  |         util.set_nonblock(self.fd) | 
					
						
							| 
									
										
										
										
											2017-03-12 19:55:56 -04:00
										 |  |  |         self.mcu_freq = 0 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |         self.data = "" | 
					
						
							| 
									
										
										
										
											2016-11-27 17:45:58 -05:00
										 |  |  |         reactor.register_fd(self.fd, self.process_kbd) | 
					
						
							| 
									
										
										
										
											2018-09-02 12:31:36 -04:00
										 |  |  |         reactor.register_callback(self.connect) | 
					
						
							| 
									
										
										
										
											2017-06-21 15:50:41 -04:00
										 |  |  |         self.local_commands = { | 
					
						
							| 
									
										
										
										
											2021-10-24 21:19:45 -04:00
										 |  |  |             "SET": self.command_SET, | 
					
						
							| 
									
										
										
										
											2022-07-29 13:30:39 -04:00
										 |  |  |             "DUMP": self.command_DUMP, "FILEDUMP": self.command_FILEDUMP, | 
					
						
							| 
									
										
										
										
											2017-09-06 15:40:23 -04:00
										 |  |  |             "DELAY": self.command_DELAY, "FLOOD": self.command_FLOOD, | 
					
						
							| 
									
										
										
										
											2017-09-06 16:34:55 -04:00
										 |  |  |             "SUPPRESS": self.command_SUPPRESS, "STATS": self.command_STATS, | 
					
						
							|  |  |  |             "LIST": self.command_LIST, "HELP": self.command_HELP, | 
					
						
							| 
									
										
										
										
											2017-06-21 15:50:41 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |         self.eval_globals = {} | 
					
						
							| 
									
										
										
										
											2016-11-27 17:45:58 -05:00
										 |  |  |     def connect(self, eventtime): | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |         self.output(help_txt) | 
					
						
							|  |  |  |         self.output("="*20 + " attempting to connect " + "="*20) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:13:15 -05:00
										 |  |  |         if self.canbus_iface is not None: | 
					
						
							|  |  |  |             self.ser.connect_canbus(self.serialport, self.canbus_nodeid, | 
					
						
							|  |  |  |                                     self.canbus_iface) | 
					
						
							|  |  |  |         elif self.baud: | 
					
						
							| 
									
										
										
										
											2021-01-30 00:01:23 -05:00
										 |  |  |             self.ser.connect_uart(self.serialport, self.baud) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.ser.connect_pipe(self.serialport) | 
					
						
							| 
									
										
										
										
											2019-06-20 22:08:38 -04:00
										 |  |  |         msgparser = self.ser.get_msgparser() | 
					
						
							| 
									
										
										
										
											2021-02-18 14:01:40 -05:00
										 |  |  |         message_count = len(msgparser.get_messages()) | 
					
						
							|  |  |  |         version, build_versions = msgparser.get_version_info() | 
					
						
							|  |  |  |         self.output("Loaded %d commands (%s / %s)" | 
					
						
							|  |  |  |                     % (message_count, version, build_versions)) | 
					
						
							| 
									
										
										
										
											2018-04-03 12:13:06 -04:00
										 |  |  |         self.output("MCU config: %s" % (" ".join( | 
					
						
							| 
									
										
										
										
											2021-02-18 14:01:40 -05:00
										 |  |  |             ["%s=%s" % (k, v) for k, v in msgparser.get_constants().items()]))) | 
					
						
							| 
									
										
										
										
											2017-09-18 21:41:00 -04:00
										 |  |  |         self.clocksync.connect(self.ser) | 
					
						
							| 
									
										
										
										
											2017-04-25 11:15:15 -04:00
										 |  |  |         self.ser.handle_default = self.handle_default | 
					
						
							| 
									
										
										
										
											2019-06-20 17:36:46 -04:00
										 |  |  |         self.ser.register_response(self.handle_output, '#output') | 
					
						
							| 
									
										
										
										
											2018-04-03 12:13:06 -04:00
										 |  |  |         self.mcu_freq = msgparser.get_constant_float('CLOCK_FREQ') | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |         self.output("="*20 + "       connected       " + "="*20) | 
					
						
							| 
									
										
										
										
											2016-11-27 17:45:58 -05:00
										 |  |  |         return self.reactor.NEVER | 
					
						
							| 
									
										
										
										
											2017-04-25 11:16:02 -04:00
										 |  |  |     def output(self, msg): | 
					
						
							|  |  |  |         sys.stdout.write("%s\n" % (msg,)) | 
					
						
							|  |  |  |         sys.stdout.flush() | 
					
						
							| 
									
										
										
										
											2017-04-25 11:15:15 -04:00
										 |  |  |     def handle_default(self, params): | 
					
						
							| 
									
										
										
										
											2018-05-16 09:27:50 -04:00
										 |  |  |         tdiff = params['#receive_time'] - self.start_time | 
					
						
							| 
									
										
										
										
											2019-06-20 22:08:38 -04:00
										 |  |  |         msg = self.ser.get_msgparser().format_params(params) | 
					
						
							|  |  |  |         self.output("%07.3f: %s" % (tdiff, msg)) | 
					
						
							| 
									
										
										
										
											2018-05-16 09:27:50 -04:00
										 |  |  |     def handle_output(self, params): | 
					
						
							|  |  |  |         tdiff = params['#receive_time'] - self.start_time | 
					
						
							|  |  |  |         self.output("%07.3f: %s: %s" % (tdiff, params['#name'], params['#msg'])) | 
					
						
							| 
									
										
										
										
											2017-09-06 16:34:55 -04:00
										 |  |  |     def handle_suppress(self, params): | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     def update_evals(self, eventtime): | 
					
						
							| 
									
										
										
										
											2017-03-12 19:55:56 -04:00
										 |  |  |         self.eval_globals['freq'] = self.mcu_freq | 
					
						
							| 
									
										
										
										
											2017-09-18 21:41:00 -04:00
										 |  |  |         self.eval_globals['clock'] = self.clocksync.get_clock(eventtime) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |     def command_SET(self, parts): | 
					
						
							| 
									
										
										
										
											2016-06-11 22:31:05 -04:00
										 |  |  |         val = parts[2] | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2017-04-25 11:19:35 -04:00
										 |  |  |             val = float(val) | 
					
						
							| 
									
										
										
										
											2016-06-11 22:31:05 -04:00
										 |  |  |         except ValueError: | 
					
						
							| 
									
										
										
										
											2017-04-25 11:19:35 -04:00
										 |  |  |             pass | 
					
						
							| 
									
										
										
										
											2016-06-11 22:31:05 -04:00
										 |  |  |         self.eval_globals[parts[1]] = val | 
					
						
							| 
									
										
										
										
											2022-07-29 13:30:39 -04:00
										 |  |  |     def command_DUMP(self, parts, filename=None): | 
					
						
							|  |  |  |         # Extract command args | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             addr = int(parts[1], 0) | 
					
						
							|  |  |  |             count = int(parts[2], 0) | 
					
						
							|  |  |  |             order = [2, 0, 1, 0][(addr | count) & 3] | 
					
						
							|  |  |  |             if len(parts) > 3: | 
					
						
							|  |  |  |                 order = {'32': 2, '16': 1, '8': 0}[parts[3]] | 
					
						
							|  |  |  |         except ValueError as e: | 
					
						
							|  |  |  |             self.output("Error: %s" % (str(e),)) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         bsize = 1 << order | 
					
						
							|  |  |  |         # Query data from mcu | 
					
						
							|  |  |  |         vals = [] | 
					
						
							|  |  |  |         for i in range((count + bsize - 1) >> order): | 
					
						
							|  |  |  |             caddr = addr + (i << order) | 
					
						
							|  |  |  |             cmd = "debug_read order=%d addr=%d" % (order, caddr) | 
					
						
							|  |  |  |             params = self.ser.send_with_response(cmd, "debug_result") | 
					
						
							|  |  |  |             vals.append(params['val']) | 
					
						
							|  |  |  |         # Report data | 
					
						
							|  |  |  |         if filename is None and order == 2: | 
					
						
							|  |  |  |             # Common 32bit hex dump | 
					
						
							|  |  |  |             for i in range((len(vals) + 3) // 4): | 
					
						
							|  |  |  |                 p = i * 4 | 
					
						
							|  |  |  |                 hexvals = " ".join(["%08x" % (v,) for v in vals[p:p+4]]) | 
					
						
							|  |  |  |                 self.output("%08x  %s" % (addr + p * 4, hexvals)) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         # Convert to byte format | 
					
						
							|  |  |  |         data = bytearray() | 
					
						
							|  |  |  |         for val in vals: | 
					
						
							|  |  |  |             for b in range(bsize): | 
					
						
							|  |  |  |                 data.append((val >> (8 * b)) & 0xff) | 
					
						
							|  |  |  |         data = data[:count] | 
					
						
							|  |  |  |         if filename is not None: | 
					
						
							|  |  |  |             f = open(filename, 'wb') | 
					
						
							|  |  |  |             f.write(data) | 
					
						
							|  |  |  |             f.close() | 
					
						
							|  |  |  |             self.output("Wrote %d bytes to '%s'" % (len(data), filename)) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         for i in range((count + 15) // 16): | 
					
						
							|  |  |  |             p = i * 16 | 
					
						
							|  |  |  |             paddr = addr + p | 
					
						
							|  |  |  |             d = data[p:p+16] | 
					
						
							|  |  |  |             hexbytes = " ".join(["%02x" % (v,) for v in d]) | 
					
						
							|  |  |  |             pb = "".join([chr(v) if v >= 0x20 and v < 0x7f else '.' for v in d]) | 
					
						
							|  |  |  |             o = "%08x  %-47s  |%s|" % (paddr, hexbytes, pb) | 
					
						
							|  |  |  |             self.output("%s %s" % (o[:34], o[34:])) | 
					
						
							|  |  |  |     def command_FILEDUMP(self, parts): | 
					
						
							|  |  |  |         self.command_DUMP(parts[1:], filename=parts[1]) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |     def command_DELAY(self, parts): | 
					
						
							| 
									
										
										
										
											2017-06-21 15:50:41 -04:00
										 |  |  |         try: | 
					
						
							|  |  |  |             val = int(parts[1]) | 
					
						
							|  |  |  |         except ValueError as e: | 
					
						
							|  |  |  |             self.output("Error: %s" % (str(e),)) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2018-02-27 14:16:16 -05:00
										 |  |  |             self.ser.send(' '.join(parts[2:]), minclock=val) | 
					
						
							| 
									
										
										
										
											2017-06-21 15:50:41 -04:00
										 |  |  |         except msgproto.error as e: | 
					
						
							|  |  |  |             self.output("Error: %s" % (str(e),)) | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2017-09-06 15:40:23 -04:00
										 |  |  |     def command_FLOOD(self, parts): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             count = int(parts[1]) | 
					
						
							|  |  |  |             delay = float(parts[2]) | 
					
						
							|  |  |  |         except ValueError as e: | 
					
						
							|  |  |  |             self.output("Error: %s" % (str(e),)) | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2018-02-27 14:16:16 -05:00
										 |  |  |         msg = ' '.join(parts[3:]) | 
					
						
							|  |  |  |         delay_clock = int(delay * self.mcu_freq) | 
					
						
							|  |  |  |         msg_clock = int(self.clocksync.get_clock(self.reactor.monotonic()) | 
					
						
							|  |  |  |                         + self.mcu_freq * .200) | 
					
						
							| 
									
										
										
										
											2017-09-06 15:40:23 -04:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2018-02-27 14:16:16 -05:00
										 |  |  |             for i in range(count): | 
					
						
							|  |  |  |                 next_clock = msg_clock + delay_clock | 
					
						
							|  |  |  |                 self.ser.send(msg, minclock=msg_clock, reqclock=next_clock) | 
					
						
							|  |  |  |                 msg_clock = next_clock | 
					
						
							| 
									
										
										
										
											2017-09-06 15:40:23 -04:00
										 |  |  |         except msgproto.error as e: | 
					
						
							|  |  |  |             self.output("Error: %s" % (str(e),)) | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2017-09-06 16:34:55 -04:00
										 |  |  |     def command_SUPPRESS(self, parts): | 
					
						
							|  |  |  |         oid = None | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             name = parts[1] | 
					
						
							|  |  |  |             if len(parts) > 2: | 
					
						
							|  |  |  |                 oid = int(parts[2]) | 
					
						
							|  |  |  |         except ValueError as e: | 
					
						
							|  |  |  |             self.output("Error: %s" % (str(e),)) | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2019-06-20 17:36:46 -04:00
										 |  |  |         self.ser.register_response(self.handle_suppress, name, oid) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:49:42 -04:00
										 |  |  |     def command_STATS(self, parts): | 
					
						
							| 
									
										
										
										
											2017-09-18 21:41:00 -04:00
										 |  |  |         curtime = self.reactor.monotonic() | 
					
						
							|  |  |  |         self.output(' '.join([self.ser.stats(curtime), | 
					
						
							|  |  |  |                               self.clocksync.stats(curtime)])) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:40:32 -04:00
										 |  |  |     def command_LIST(self, parts): | 
					
						
							|  |  |  |         self.update_evals(self.reactor.monotonic()) | 
					
						
							| 
									
										
										
										
											2019-06-20 22:08:38 -04:00
										 |  |  |         mp = self.ser.get_msgparser() | 
					
						
							| 
									
										
										
										
											2021-02-04 16:33:03 -05:00
										 |  |  |         cmds = [msgformat for msgtag, msgtype, msgformat in mp.get_messages() | 
					
						
							| 
									
										
										
										
											2021-02-18 14:01:40 -05:00
										 |  |  |                 if msgtype == 'command'] | 
					
						
							| 
									
										
										
										
											2017-08-07 20:40:32 -04:00
										 |  |  |         out = "Available mcu commands:" | 
					
						
							| 
									
										
										
										
											2021-02-18 14:01:40 -05:00
										 |  |  |         out += "\n  ".join([""] + sorted(cmds)) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:40:32 -04:00
										 |  |  |         out += "\nAvailable artificial commands:" | 
					
						
							|  |  |  |         out += "\n  ".join([""] + [n for n in sorted(self.local_commands)]) | 
					
						
							|  |  |  |         out += "\nAvailable local variables:" | 
					
						
							| 
									
										
										
										
											2019-02-27 13:00:30 -05:00
										 |  |  |         lvars = sorted(self.eval_globals.items()) | 
					
						
							|  |  |  |         out += "\n  ".join([""] + ["%s: %s" % (k, v) for k, v in lvars]) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:40:32 -04:00
										 |  |  |         self.output(out) | 
					
						
							| 
									
										
										
										
											2017-08-07 20:05:19 -04:00
										 |  |  |     def command_HELP(self, parts): | 
					
						
							|  |  |  |         self.output(help_txt) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     def translate(self, line, eventtime): | 
					
						
							|  |  |  |         evalparts = re_eval.split(line) | 
					
						
							|  |  |  |         if len(evalparts) > 1: | 
					
						
							|  |  |  |             self.update_evals(eventtime) | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 for i in range(1, len(evalparts), 2): | 
					
						
							| 
									
										
										
										
											2017-08-07 20:40:32 -04:00
										 |  |  |                     e = eval(evalparts[i], dict(self.eval_globals)) | 
					
						
							| 
									
										
										
										
											2017-04-25 11:19:35 -04:00
										 |  |  |                     if type(e) == type(0.): | 
					
						
							|  |  |  |                         e = int(e) | 
					
						
							|  |  |  |                     evalparts[i] = str(e) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |             except: | 
					
						
							| 
									
										
										
										
											2017-04-25 11:16:02 -04:00
										 |  |  |                 self.output("Unable to evaluate: %s" % (line,)) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |                 return None | 
					
						
							|  |  |  |             line = ''.join(evalparts) | 
					
						
							| 
									
										
										
										
											2017-04-25 11:16:02 -04:00
										 |  |  |             self.output("Eval: %s" % (line,)) | 
					
						
							| 
									
										
										
										
											2023-01-07 11:53:09 -05:00
										 |  |  |         line = line.strip() | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |         if line: | 
					
						
							|  |  |  |             parts = line.split() | 
					
						
							|  |  |  |             if parts[0] in self.local_commands: | 
					
						
							|  |  |  |                 self.local_commands[parts[0]](parts) | 
					
						
							|  |  |  |                 return None | 
					
						
							| 
									
										
										
										
											2018-02-27 14:16:16 -05:00
										 |  |  |         return line | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     def process_kbd(self, eventtime): | 
					
						
							| 
									
										
										
										
											2021-10-31 13:40:11 -04:00
										 |  |  |         self.data += str(os.read(self.fd, 4096).decode()) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         kbdlines = self.data.split('\n') | 
					
						
							|  |  |  |         for line in kbdlines[:-1]: | 
					
						
							|  |  |  |             line = line.strip() | 
					
						
							|  |  |  |             cpos = line.find('#') | 
					
						
							|  |  |  |             if cpos >= 0: | 
					
						
							|  |  |  |                 line = line[:cpos] | 
					
						
							|  |  |  |                 if not line: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |             msg = self.translate(line.strip(), eventtime) | 
					
						
							|  |  |  |             if msg is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2018-02-27 14:16:16 -05:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 self.ser.send(msg) | 
					
						
							|  |  |  |             except msgproto.error as e: | 
					
						
							|  |  |  |                 self.output("Error: %s" % (str(e),)) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |         self.data = kbdlines[-1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2021-02-07 14:20:47 -05:00
										 |  |  |     usage = "%prog [options] <serialdevice>" | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     opts = optparse.OptionParser(usage) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:30:21 -05:00
										 |  |  |     opts.add_option("-v", action="store_true", dest="verbose", | 
					
						
							|  |  |  |                     help="enable debug messages") | 
					
						
							| 
									
										
										
										
											2021-02-07 14:20:47 -05:00
										 |  |  |     opts.add_option("-b", "--baud", type="int", dest="baud", help="baud rate") | 
					
						
							| 
									
										
										
										
											2021-02-07 17:13:15 -05:00
										 |  |  |     opts.add_option("-c", "--canbus_iface", dest="canbus_iface", | 
					
						
							|  |  |  |                     help="Use CAN bus interface; serialdevice is the chip UUID") | 
					
						
							|  |  |  |     opts.add_option("-i", "--canbus_nodeid", type="int", dest="canbus_nodeid", | 
					
						
							|  |  |  |                     default=64, help="The CAN nodeid to use (default 64)") | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     options, args = opts.parse_args() | 
					
						
							| 
									
										
										
										
											2021-02-07 14:20:47 -05:00
										 |  |  |     if len(args) != 1: | 
					
						
							|  |  |  |         opts.error("Incorrect number of arguments") | 
					
						
							|  |  |  |     serialport = args[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     baud = options.baud | 
					
						
							|  |  |  |     if baud is None and not (serialport.startswith("/dev/rpmsg_") | 
					
						
							|  |  |  |                              or serialport.startswith("/tmp/")): | 
					
						
							|  |  |  |         baud = 250000 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:30:21 -05:00
										 |  |  |     debuglevel = logging.INFO | 
					
						
							|  |  |  |     if options.verbose: | 
					
						
							|  |  |  |         debuglevel = logging.DEBUG | 
					
						
							|  |  |  |     logging.basicConfig(level=debuglevel) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     r = reactor.Reactor() | 
					
						
							| 
									
										
										
										
											2021-02-07 17:13:15 -05:00
										 |  |  |     kbd = KeyboardReader(r, serialport, baud, options.canbus_iface, | 
					
						
							|  |  |  |                          options.canbus_nodeid) | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  |     try: | 
					
						
							|  |  |  |         r.run() | 
					
						
							|  |  |  |     except KeyboardInterrupt: | 
					
						
							|  |  |  |         sys.stdout.write("\n") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     main() |