You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					94 lines
				
				3.1 KiB
			
		
		
			
		
	
	
					94 lines
				
				3.1 KiB
			| 
											8 years ago
										 | #!/usr/bin/env python
 | ||
|  | 
 | ||
|  | # Given an interesting CSV file of CAN messages and a list of background CAN
 | ||
|  | # messages, print which bits in the interesting file have never appeared
 | ||
|  | # in the background files.
 | ||
|  | 
 | ||
|  | # Expects the CSV file to be in the format from can_logger.py
 | ||
|  | # Bus,MessageID,Message,MessageLength
 | ||
|  | # 0,0x292,0x040000001068,6
 | ||
|  | 
 | ||
|  | # The old can_logger.py format is also supported:
 | ||
|  | # Bus,MessageID,Message
 | ||
|  | # 0,344,c000c00000000000
 | ||
|  | 
 | ||
|  | 
 | ||
|  | import binascii
 | ||
|  | import csv
 | ||
|  | import sys
 | ||
|  | from panda import Panda
 | ||
|  | 
 | ||
|  | class Message():
 | ||
|  |   """Details about a specific message ID."""
 | ||
|  |   def __init__(self, message_id):
 | ||
|  |     self.message_id = message_id
 | ||
|  |     self.data = {}  # keyed by hex string encoded message data
 | ||
|  |     self.ones = [0] * 8   # bit set if 1 is seen
 | ||
|  |     self.zeros = [0] * 8  # bit set if 0 has been seen
 | ||
|  | 
 | ||
|  |   def printBitDiff(self, other):
 | ||
|  |     """Prints bits that are set or cleared compared to other background."""
 | ||
|  |     for i in xrange(len(self.ones)):
 | ||
|  |       new_ones = ((~other.ones[i]) & 0xff) & self.ones[i]
 | ||
|  |       if new_ones:
 | ||
|  |         print 'id %s new one  at byte %d bitmask %d' % (
 | ||
|  |             self.message_id, i, new_ones)
 | ||
|  |       new_zeros = ((~other.zeros[i]) & 0xff) & self.zeros[i]
 | ||
|  |       if new_zeros:
 | ||
|  |         print 'id %s new zero at byte %d bitmask %d' % (
 | ||
|  |             self.message_id, i, new_zeros)
 | ||
|  | 
 | ||
|  | 
 | ||
|  | class Info():
 | ||
|  |   """A collection of Messages."""
 | ||
|  | 
 | ||
|  |   def __init__(self):
 | ||
|  |     self.messages = {}  # keyed by MessageID
 | ||
|  | 
 | ||
|  |   def load(self, filename):
 | ||
|  |     """Given a CSV file, adds information about message IDs and their values."""
 | ||
|  |     with open(filename, 'rb') as input:
 | ||
|  |       reader = csv.reader(input)
 | ||
|  |       next(reader, None)  # skip the CSV header
 | ||
|  |       for row in reader:
 | ||
| 
											8 years ago
										 |         bus = row[0]
 | ||
| 
											8 years ago
										 |         if row[1].startswith('0x'):
 | ||
|  |           message_id = row[1][2:]  # remove leading '0x'
 | ||
|  |         else:
 | ||
|  |           message_id = hex(int(row[1]))[2:]  # old message IDs are in decimal
 | ||
| 
											8 years ago
										 |         message_id = '%s:%s' % (bus, message_id)
 | ||
| 
											8 years ago
										 |         if row[1].startswith('0x'):
 | ||
|  |           data = row[2][2:]  # remove leading '0x'
 | ||
|  |         else:
 | ||
|  |           data = row[2]
 | ||
|  |         if message_id not in self.messages:
 | ||
|  |           self.messages[message_id] = Message(message_id)
 | ||
|  |         message = self.messages[message_id]
 | ||
|  |         if data not in self.messages[message_id].data:
 | ||
|  |           message.data[data] = True
 | ||
|  |         bytes = bytearray.fromhex(data)
 | ||
|  |         for i in xrange(len(bytes)):
 | ||
|  |           message.ones[i] = message.ones[i] | int(bytes[i])
 | ||
|  |           # Inverts the data and masks it to a byte to get the zeros as ones.
 | ||
|  |           message.zeros[i] = message.zeros[i] | ( (~int(bytes[i])) & 0xff)
 | ||
|  | 
 | ||
|  | def PrintUnique(interesting_file, background_files):
 | ||
|  |   background = Info()
 | ||
|  |   for background_file in background_files:
 | ||
|  |     background.load(background_file)
 | ||
|  |   interesting = Info()
 | ||
|  |   interesting.load(interesting_file)
 | ||
| 
											8 years ago
										 |   for message_id in sorted(interesting.messages):
 | ||
| 
											8 years ago
										 |     if message_id not in background.messages:
 | ||
|  |       print 'New message_id: %s' % message_id
 | ||
|  |     else:
 | ||
|  |       interesting.messages[message_id].printBitDiff(
 | ||
|  |           background.messages[message_id])
 | ||
|  | 
 | ||
|  | 
 | ||
|  | if __name__ == "__main__":
 | ||
|  |   if len(sys.argv) < 3:
 | ||
|  |     print 'Usage:\n%s interesting.csv background*.csv' % sys.argv[0]
 | ||
|  |     sys.exit(0)
 | ||
|  |   PrintUnique(sys.argv[1], sys.argv[2:])
 |