Last active
June 4, 2017 16:32
-
-
Save knoguchi/4fc486a0cc39c1fd256d2fb6f619ee98 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import argparse | |
from collections import namedtuple | |
class Record: | |
def __init__(self, crtime=0.00000, ch=1, hexid=0x000, dir="Rx", stat="d", data=None, length=0, bitcount=0, decid=0): | |
self.crtime = crtime | |
self.ch = ch | |
self.hexid = hexid | |
self.dir = dir | |
self.stat = stat | |
self.data = data or [] | |
self.length = length | |
self.bitcount = bitcount | |
self.decid = decid | |
@property | |
def dlc(self): | |
return len(self.data) | |
@classmethod | |
def parse_from_file(cls, input_file): | |
""" | |
The log format is fixed header fields, variable length data, ordered key-value pairs | |
header fields: crtime, ch, hexid, dir, stat, dlc | |
variable data: byte * dlc | |
""" | |
HEADER_TYPES = ( | |
('crtime', float), | |
('ch', int), | |
('hexid', lambda s: int(s, 16)), | |
('dir', str), | |
('stat', str), | |
('dlc', int), | |
) | |
HEADER_LENGTH = len(HEADER_TYPES) | |
Header = namedtuple("Header", [field for field, _ in HEADER_TYPES]) | |
for line in input_file: | |
fields = line.split() | |
if not re.match("1|2", fields[1]): | |
# ignore non-data rows | |
continue | |
# extract header | |
header_values = fields[:HEADER_LENGTH] | |
header_values = [func(value) for (field, func), value in zip(HEADER_TYPES, header_values)] | |
header = Header(*header_values) | |
# extract data | |
data = map(lambda x: int(x, 16), fields[HEADER_LENGTH:][:header.dlc]) | |
# extract trailer | |
length = fields[-7] | |
bitcount = fields[-4] | |
decid = fields[-1] | |
yield cls( | |
crtime=header.crtime, | |
ch=header.ch, | |
hexid=header.hexid, | |
dir=header.dir, | |
stat=header.stat, | |
data=data, | |
length=length, | |
bitcount=bitcount, | |
decid=decid | |
) | |
def __str__(self): | |
return '%f %d %03X %s %d %s' % ( | |
self.crtime, self.ch, self.hexid, self.dir, self.dlc, | |
' '.join(["%02X" % byte for byte in self.data]) | |
) | |
def main(): | |
parser = argparse.ArgumentParser(description='CanlogFilter') | |
parser.add_argument('inputFile', help='Input file path') | |
parser.add_argument('--difftime', '-d', action='store_const', const=True, default=False, help='Print with difftime') | |
group = parser.add_mutually_exclusive_group() | |
group.add_argument('--pickup', '-u', nargs='*', type=lambda x: int(x, 16), help='pick up records') | |
group.add_argument('--dropoff', '-o', nargs='*', type=lambda x: int(x, 16), help='drop off records') | |
args = parser.parse_args() | |
with open(args.inputFile) as input_file: | |
canlog = Record.parse_from_file(input_file) | |
if args.pickup: | |
canlog = pick_log(canlog, args.pickup) | |
elif args.dropoff: | |
canlog = drop_log(canlog, args.dropoff) | |
if args.difftime: | |
printlog_with_diff_time(canlog) | |
else: | |
printlog(canlog) | |
def pick_log(canlog, ids): | |
return filter(lambda rec: rec.hexid in ids, canlog) | |
def drop_log(canlog, ids): | |
return filter(lambda rec: rec.hexid not in ids, canlog) | |
def printlog(canlog): | |
for rec in canlog: | |
print rec | |
def printlog_with_diff_time(canlog): | |
prevtime = 0 | |
for rec in canlog: | |
difftime = rec.crtime - prevtime | |
print '%f %s' % (difftime, rec) | |
prevtime = rec.crtime | |
if __name__ == '__main__': main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
48行目はPython2でしか動かない。Python3では入れ子のタプルの展開ができなくなったため。