#!/usr/bin/env python3
import os
import sys
import bz2
import urllib . parse
import capnp
import warnings
from typing import Iterable , Iterator
from cereal import log as capnp_log
from openpilot . tools . lib . filereader import FileReader
LogIterable = Iterable [ capnp . _DynamicStructReader ]
class LogReader :
def __init__ ( self , fn , canonicalize = True , only_union_types = False , sort_by_time = False , dat = None ) :
self . data_version = None
self . _only_union_types = only_union_types
ext = None
if not dat :
_ , ext = os . path . splitext ( urllib . parse . urlparse ( fn ) . path )
if ext not in ( ' ' , ' .bz2 ' ) :
# old rlogs weren't bz2 compressed
raise Exception ( f " unknown extension { ext } " )
with FileReader ( fn ) as f :
dat = f . read ( )
if ext == " .bz2 " or dat . startswith ( b ' BZh9 ' ) :
dat = bz2 . decompress ( dat )
ents = capnp_log . Event . read_multiple_bytes ( dat )
_ents = [ ]
try :
for e in ents :
_ents . append ( e )
except capnp . KjException :
warnings . warn ( " Corrupted events detected " , RuntimeWarning , stacklevel = 1 )
self . _ents = list ( sorted ( _ents , key = lambda x : x . logMonoTime ) if sort_by_time else _ents )
self . _ts = [ x . logMonoTime for x in self . _ents ]
@classmethod
def from_bytes ( cls , dat ) :
return cls ( " " , dat = dat )
def __iter__ ( self ) - > Iterator [ capnp . _DynamicStructReader ] :
for ent in self . _ents :
if self . _only_union_types :
try :
ent . which ( )
yield ent
except capnp . lib . capnp . KjException :
pass
else :
yield ent
if __name__ == " __main__ " :
import codecs
# capnproto <= 0.8.0 throws errors converting byte data to string
# below line catches those errors and replaces the bytes with \x__
codecs . register_error ( " strict " , codecs . backslashreplace_errors )
log_path = sys . argv [ 1 ]
lr = LogReader ( log_path , sort_by_time = True )
for msg in lr :
print ( msg )