@ -21,6 +21,17 @@ __version__ = "1.2"
@@ -21,6 +21,17 @@ __version__ = "1.2"
import struct , sys
from pypreprocessor import pypreprocessor
#exclude
if sys . version [ : 3 ] . split ( ' . ' ) [ 0 ] == ' 2 ' :
pypreprocessor . defines . append ( ' python2 ' )
if sys . version [ : 3 ] . split ( ' . ' ) [ 0 ] == ' 3 ' :
pypreprocessor . defines . append ( ' python3 ' )
pypreprocessor . parse ( )
#endexclude
class SDLog2Parser :
BLOCK_SIZE = 8192
MSG_HEADER_LEN = 3
@ -65,7 +76,11 @@ class SDLog2Parser:
@@ -65,7 +76,11 @@ class SDLog2Parser:
self . __msg_descrs = { } # message descriptions by message type map
self . __msg_labels = { } # message labels by message name map
self . __msg_names = [ ] # message names in the same order as FORMAT messages
self . __buffer = " " # buffer for input binary data
#ifdef python2
self . __buffer = " " # buffer, python2
#else
self . __buffer = bytearray ( ) # buffer for input binary data
#endif
self . __ptr = 0 # read pointer in buffer
self . __csv_columns = [ ] # CSV file columns in correct order in format "MSG.label"
self . __csv_data = { } # current values for all columns
@ -114,15 +129,24 @@ class SDLog2Parser:
@@ -114,15 +129,24 @@ class SDLog2Parser:
self . __buffer = self . __buffer [ self . __ptr : ] + chunk
self . __ptr = 0
while self . __bytesLeft ( ) > = self . MSG_HEADER_LEN :
#ifdef python2
head1 = ord ( self . __buffer [ self . __ptr ] )
head2 = ord ( self . __buffer [ self . __ptr + 1 ] )
#else
head1 = self . __buffer [ self . __ptr ]
head2 = self . __buffer [ self . __ptr + 1 ]
#endif
if ( head1 != self . MSG_HEAD1 or head2 != self . MSG_HEAD2 ) :
if self . __correct_errors :
self . __ptr + = 1
continue
else :
raise Exception ( " Invalid header at %i (0x %X ): %02X %02X , must be %02X %02X " % ( bytes_read + self . __ptr , bytes_read + self . __ptr , head1 , head2 , self . MSG_HEAD1 , self . MSG_HEAD2 ) )
#ifdef python2
msg_type = ord ( self . __buffer [ self . __ptr + 2 ] )
#else
msg_type = self . __buffer [ self . __ptr + 2 ]
#endif
if msg_type == self . MSG_TYPE_FORMAT :
# parse FORMAT message
if self . __bytesLeft ( ) < self . MSG_FORMAT_PACKET_LEN :
@ -170,7 +194,11 @@ class SDLog2Parser:
@@ -170,7 +194,11 @@ class SDLog2Parser:
if self . __file != None :
print >> self . __file , self . __csv_delim . join ( self . __csv_columns )
else :
#ifdef python2
print self . __csv_delim . join ( self . __csv_columns )
#else
print ( self . __csv_delim . join ( self . __csv_columns ) )
#endif
def __printCSVRow ( self ) :
s = [ ]
@ -185,16 +213,26 @@ class SDLog2Parser:
@@ -185,16 +213,26 @@ class SDLog2Parser:
if self . __file != None :
print >> self . __file , self . __csv_delim . join ( s )
else :
#ifdef python2
print self . __csv_delim . join ( s )
#else
print ( self . __csv_delim . join ( s ) )
#endif
def __parseMsgDescr ( self ) :
data = struct . unpack ( self . MSG_FORMAT_STRUCT , self . __buffer [ self . __ptr + 3 : self . __ptr + self . MSG_FORMAT_PACKET_LEN ] )
msg_type = data [ 0 ]
if msg_type != self . MSG_TYPE_FORMAT :
msg_length = data [ 1 ]
#ifdef python2
msg_name = data [ 2 ] . strip ( " \0 " )
msg_format = data [ 3 ] . strip ( " \0 " )
msg_labels = data [ 4 ] . strip ( " \0 " ) . split ( " , " )
#else
msg_name = str ( data [ 2 ] , ' ascii ' ) . strip ( " \0 " )
msg_format = str ( data [ 3 ] , ' ascii ' ) . strip ( " \0 " )
msg_labels = str ( data [ 4 ] , ' ascii ' ) . strip ( " \0 " ) . split ( " , " )
#endif
# Convert msg_format to struct.unpack format string
msg_struct = " "
msg_mults = [ ]
@ -211,8 +249,13 @@ class SDLog2Parser:
@@ -211,8 +249,13 @@ class SDLog2Parser:
self . __msg_names . append ( msg_name )
if self . __debug_out :
if self . __filterMsg ( msg_name ) != None :
#ifdef python2
print " MSG FORMAT: type = %i , length = %i , name = %s , format = %s , labels = %s , struct = %s , mults = %s " % (
msg_type , msg_length , msg_name , msg_format , str ( msg_labels ) , msg_struct , msg_mults )
#else
print ( " MSG FORMAT: type = %i , length = %i , name = %s , format = %s , labels = %s , struct = %s , mults = %s " % (
msg_type , msg_length , msg_name , msg_format , str ( msg_labels ) , msg_struct , msg_mults ) )
#endif
self . __ptr + = self . MSG_FORMAT_PACKET_LEN
def __parseMsg ( self , msg_descr ) :
@ -223,7 +266,11 @@ class SDLog2Parser:
@@ -223,7 +266,11 @@ class SDLog2Parser:
show_fields = self . __filterMsg ( msg_name )
if ( show_fields != None ) :
data = list ( struct . unpack ( msg_struct , self . __buffer [ self . __ptr + self . MSG_HEADER_LEN : self . __ptr + msg_length ] ) )
#ifdef python2
for i in xrange ( len ( data ) ) :
#else
for i in range ( len ( data ) ) :
#endif
if type ( data [ i ] ) is str :
data [ i ] = data [ i ] . strip ( " \0 " )
m = msg_mults [ i ]
@ -231,14 +278,26 @@ class SDLog2Parser:
@@ -231,14 +278,26 @@ class SDLog2Parser:
data [ i ] = data [ i ] * m
if self . __debug_out :
s = [ ]
#ifdef python2
for i in xrange ( len ( data ) ) :
#else
for i in range ( len ( data ) ) :
#endif
label = msg_labels [ i ]
if show_fields == " * " or label in show_fields :
s . append ( label + " = " + str ( data [ i ] ) )
#ifdef python2
print " MSG %s : %s " % ( msg_name , " , " . join ( s ) )
#else
print ( " MSG %s : %s " % ( msg_name , " , " . join ( s ) ) )
#endif
else :
# update CSV data buffer
#ifdef python2
for i in xrange ( len ( data ) ) :
#else
for i in range ( len ( data ) ) :
#endif
label = msg_labels [ i ]
if label in show_fields :
self . __csv_data [ msg_name + " _ " + label ] = data [ i ]
@ -250,6 +309,7 @@ class SDLog2Parser:
@@ -250,6 +309,7 @@ class SDLog2Parser:
def _main ( ) :
if len ( sys . argv ) < 2 :
#ifdef python2
print " Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[.field1,field2,...]] [-t TIME_MSG_NAME] \n "
print " \t -v \t Use plain debug output instead of CSV. \n "
print " \t -e \t Recover from errors. \n "
@ -258,6 +318,16 @@ def _main():
@@ -258,6 +318,16 @@ def _main():
print " \t -m MSG[.field1,field2,...] \n \t \t Dump only messages of specified type, and only specified fields. \n \t \t Multiple -m options allowed. "
print " \t -t \t Specify TIME message name to group data messages by time and significantly reduce duplicate output. \n "
print " \t -fPrint to file instead of stdout "
#else
print ( " Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[.field1,field2,...]] [-t TIME_MSG_NAME] \n " )
print ( " \t -v \t Use plain debug output instead of CSV. \n " )
print ( " \t -e \t Recover from errors. \n " )
print ( " \t -d \t Use \" delimiter \" in CSV. Default is \" , \" . \n " )
print ( " \t -n \t Use \" null \" as placeholder for empty values in CSV. Default is empty. \n " )
print ( " \t -m MSG[.field1,field2,...] \n \t \t Dump only messages of specified type, and only specified fields. \n \t \t Multiple -m options allowed. " )
print ( " \t -t \t Specify TIME message name to group data messages by time and significantly reduce duplicate output. \n " )
print ( " \t -fPrint to file instead of stdout " )
#endif
return
fn = sys . argv [ 1 ]
debug_out = False