blob: 9c955c6111f25badfe1b58a861f1aec3cd2ed248 [file] [log] [blame]
Kevin O'Connor2547bb82009-04-19 11:04:59 -04001#!/usr/bin/env python
2# Script that can read from a serial device and show timestamps.
3#
4# Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
5#
6# This file may be distributed under the terms of the GNU GPLv3 license.
7
8# Usage:
9# tools/readserial.py /dev/ttyUSB0 115200
10
11import sys
12import time
13import select
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -040014import optparse
Kevin O'Connor2547bb82009-04-19 11:04:59 -040015
16# Reset time counter after this much idle time.
17RESTARTINTERVAL = 60
18# Alter timing reports based on how much time would be spent writing
19# to serial.
20ADJUSTBAUD = 1
Kevin O'Connor77443202009-12-05 14:23:27 -050021# Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
22# bits + 1 stop bit.
23BITSPERBYTE = 10
Kevin O'Connor2547bb82009-04-19 11:04:59 -040024
25def readserial(infile, logfile, baudrate):
Kevin O'Connora1dadf42009-04-26 21:24:16 -040026 lasttime = 0
Kevin O'Connor58db9c42009-12-12 13:28:38 -050027 byteadjust = 0.0
28 if ADJUSTBAUD:
29 byteadjust = float(BITSPERBYTE) / baudrate
Kevin O'Connor2547bb82009-04-19 11:04:59 -040030 while 1:
31 # Read data
32 try:
33 res = select.select([infile, sys.stdin], [], [])
34 except KeyboardInterrupt:
35 sys.stdout.write("\n")
36 break
37 if sys.stdin in res[0]:
38 # Got keyboard input - force reset on next serial input
39 sys.stdin.read(1)
Kevin O'Connora1dadf42009-04-26 21:24:16 -040040 lasttime = 0
Kevin O'Connor2547bb82009-04-19 11:04:59 -040041 if len(res[0]) == 1:
42 continue
Kevin O'Connor2547bb82009-04-19 11:04:59 -040043 d = infile.read(4096)
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -040044 if not d:
45 break
Kevin O'Connor58db9c42009-12-12 13:28:38 -050046 datatime = time.time()
47
48 datatime -= len(d) * byteadjust
Kevin O'Connor2547bb82009-04-19 11:04:59 -040049
50 # Reset start time if no data for some time
Kevin O'Connor58db9c42009-12-12 13:28:38 -050051 if datatime - lasttime > RESTARTINTERVAL:
52 starttime = datatime
Kevin O'Connor2547bb82009-04-19 11:04:59 -040053 charcount = 0
54 isnewline = 1
Kevin O'Connora53ab002009-12-05 13:44:39 -050055 msg = "\n\n======= %s (adjust=%d)\n" % (
Kevin O'Connor58db9c42009-12-12 13:28:38 -050056 time.asctime(time.localtime(datatime)), ADJUSTBAUD)
Kevin O'Connora53ab002009-12-05 13:44:39 -050057 sys.stdout.write(msg)
58 logfile.write(msg)
Kevin O'Connor58db9c42009-12-12 13:28:38 -050059 lasttime = datatime
Kevin O'Connor2547bb82009-04-19 11:04:59 -040060
61 # Translate unprintable chars; add timestamps
62 out = ""
63 for c in d:
64 if isnewline:
Kevin O'Connor58db9c42009-12-12 13:28:38 -050065 delta = datatime - starttime - (charcount * byteadjust)
Kevin O'Connor2547bb82009-04-19 11:04:59 -040066 out += "%06.3f: " % delta
67 isnewline = 0
68 oc = ord(c)
69 charcount += 1
Kevin O'Connor58db9c42009-12-12 13:28:38 -050070 datatime += byteadjust
Kevin O'Connor2547bb82009-04-19 11:04:59 -040071 if oc == 0x0d:
72 continue
73 if oc == 0x00:
74 out += "<00>\n"
75 isnewline = 1
76 continue
77 if oc == 0x0a:
78 out += "\n"
79 isnewline = 1
80 continue
81 if oc < 0x20 or oc >= 0x7f and oc != 0x09:
82 out += "<%02x>" % oc
83 continue
84 out += c
85
86 sys.stdout.write(out)
87 sys.stdout.flush()
88 logfile.write(out)
89 logfile.flush()
90
Kevin O'Connor2547bb82009-04-19 11:04:59 -040091def main():
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -040092 usage = "%prog [options] [<serialdevice> [<baud>]]"
93 opts = optparse.OptionParser(usage)
94 opts.add_option("-f", "--file",
95 action="store_false", dest="serial", default=True,
96 help="read from file instead of serialdevice")
97 opts.add_option("-n", "--no-adjust",
98 action="store_false", dest="adjustbaud", default=True,
99 help="don't adjust times by serial rate")
100 options, args = opts.parse_args()
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400101 serialport = 0
102 baud = 115200
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400103 if len(args) > 2:
104 opts.error("Too many arguments")
105 if len(args) > 0:
106 serialport = args[0]
107 if len(args) > 1:
108 baud = int(args[1])
109 global ADJUSTBAUD
110 ADJUSTBAUD=options.adjustbaud
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400111
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400112 if options.serial:
113 # Read from serial port
Kevin O'Connor94330982010-10-17 21:38:38 -0400114 try:
115 import serial
116 except ImportError:
117 print """
118Unable to find pyserial package ( http://pyserial.sourceforge.net/ ).
119On Linux machines try: yum install pyserial
120Or: apt-get install python-serial
121"""
122 sys.exit(1)
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400123 ser = serial.Serial(serialport, baud, timeout=0)
124 else:
125 # Read from a file
126 ser = open(serialport, 'rb')
127 import fcntl
128 import os
129 fcntl.fcntl(ser, fcntl.F_SETFL
130 , fcntl.fcntl(ser, fcntl.F_GETFL) | os.O_NONBLOCK)
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400131
132 logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
133 f = open(logname, 'wb')
134 readserial(ser, f, baud)
135
136if __name__ == '__main__':
137 main()