import capnp
from typing import Any
from cereal import car
from opendbc . car import structs
_FIELDS = ' __dataclass_fields__ ' # copy of dataclasses._FIELDS
def is_dataclass ( obj ) :
""" Similar to dataclasses.is_dataclass without instance type check checking """
return hasattr ( obj , _FIELDS )
def _asdictref_inner ( obj ) - > dict [ str , Any ] | Any :
if is_dataclass ( obj ) :
ret = { }
for field in getattr ( obj , _FIELDS ) : # similar to dataclasses.fields()
ret [ field ] = _asdictref_inner ( getattr ( obj , field ) )
return ret
elif isinstance ( obj , ( tuple , list ) ) :
return type ( obj ) ( _asdictref_inner ( v ) for v in obj )
else :
return obj
def asdictref ( obj ) - > dict [ str , Any ] :
"""
Similar to dataclasses . asdict without recursive type checking and copy . deepcopy
Note that the resulting dict will contain references to the original struct as a result
"""
if not is_dataclass ( obj ) :
raise TypeError ( " asdictref() should be called on dataclass instances " )
return _asdictref_inner ( obj )
def convert_to_capnp ( struct : structs . CarParams | structs . CarState | structs . CarControl . Actuators | structs . RadarData ) - > capnp . lib . capnp . _DynamicStructBuilder :
struct_dict = asdictref ( struct )
if isinstance ( struct , structs . CarParams ) :
del struct_dict [ ' lateralTuning ' ]
struct_capnp = car . CarParams . new_message ( * * struct_dict )
# this is the only union, special handling
which = struct . lateralTuning . which ( )
struct_capnp . lateralTuning . init ( which )
lateralTuning_dict = asdictref ( getattr ( struct . lateralTuning , which ) )
setattr ( struct_capnp . lateralTuning , which , lateralTuning_dict )
elif isinstance ( struct , structs . CarState ) :
struct_capnp = car . CarState . new_message ( * * struct_dict )
elif isinstance ( struct , structs . CarControl . Actuators ) :
struct_capnp = car . CarControl . Actuators . new_message ( * * struct_dict )
elif isinstance ( struct , structs . RadarData ) :
struct_capnp = car . RadarData . new_message ( * * struct_dict )
else :
raise ValueError ( f " Unsupported struct type: { type ( struct ) } " )
return struct_capnp
def convert_carControl ( struct : capnp . lib . capnp . _DynamicStructReader ) - > structs . CarControl :
# TODO: recursively handle any car struct as needed
def remove_deprecated ( s : dict ) - > dict :
return { k : v for k , v in s . items ( ) if not k . endswith ( ' DEPRECATED ' ) }
struct_dict = struct . to_dict ( )
struct_dataclass = structs . CarControl ( * * remove_deprecated ( { k : v for k , v in struct_dict . items ( ) if not isinstance ( k , dict ) } ) )
struct_dataclass . actuators = structs . CarControl . Actuators ( * * remove_deprecated ( struct_dict . get ( ' actuators ' , { } ) ) )
struct_dataclass . cruiseControl = structs . CarControl . CruiseControl ( * * remove_deprecated ( struct_dict . get ( ' cruiseControl ' , { } ) ) )
struct_dataclass . hudControl = structs . CarControl . HUDControl ( * * remove_deprecated ( struct_dict . get ( ' hudControl ' , { } ) ) )
return struct_dataclass