赞
踩
dbc文件是汽车行业常见的数据库文件,用于描述CAN总线数据的物理值、单位、发送周期、计算公式、信号名称等信息。
用Python处理dbc文件的库有很多,比如 python-can,cantools和canmatrix,甚至可以用正则表达式自行进行解析。其解析本质差不多,下面分享下canmatrix常用的一些方法。
canmatrix使用时直接"import canmatrix"即可,但是会打印出一些 "xxx is not supported"的提示信息,这是使用到的库没安装导致的。
在.\canmatrix\formats路径下有很多 xxx.py文件,这些文件用于解析相对应后缀名的文件。打开"xxx is not supported"对应的.py,安装文件中用到(import)的三方库即可。
安装canmatrix后,在\Python\PythonXX\Scripts路径下,会有一个canconvert.exe。可以直接在命令行中:
也可以用canmatrix.convert py脚本,比如:
from canmatrix import convert
convert.convert(
r'aa.dbc',
r'aa.xlsx'
)
canconvert导入导出的表格是有固定格式的,常用于临时查看dbc中的报文和信号。一般公司会有matrix特定的表格格式,这就需要特定处理了。
import canmatrix
file = r'Test.dbc'
dbs = canmatrix.formats.loadp(file)
print(type(dbs), dbs)
matrix = dbs.get('')
print(type(matrix), matrix)
for k, v in matrix.__dict__.items():
print(k, v)
for ecu in matrix.ecus:
print(type(ecu), ecu.__dict__)
for msg in matrix.frames:
print(type(msg), msg.__dict__)
for k, v in msg.__dict__.items():
print(k, v)
一些其他信息会在
attributes 字典中,比如Nm或者诊断报文。
如果有其他信息想知道,可以用类似方式打印其.__dict__查看。
for signal in msg.signals:
print(type(signal), signal.__dict__)
for k, v in signal.__dict__.items():
print(k, v)
for signalGroup in msg.signalGroups:
print(type(signalGroup), signalGroup.__dict__)
for k, v in signalGroup.__dict__.items():
print(k, v)
注意避免信号重复使用
。以下示例都是应用于vector的达芬奇开发工具,其他工具不清楚是否适用。用到的场景基本都是读取dbc中的报文和信号名称,再做一些其他处理。
一般E2E信号的名称是有特定字符的,可判断其名称来确定所在报文是否为E2E报文。再结合xml解析脚本,可以在ComCbk中自动添加回调函数的名称。
def is_signal_e2e(signal: canmatrix.Signal):
"""
判断信号是否是E2E信号,checksum or rolling_counter
"""
RCs = ("RollCnt", "RollingCounter", "AliveCounter", "Rolling_Counter", "Alive_Counter", "RollgCnt")
CRCs = ("Chksum", "Chksm", "CheckSum", "CRC")
for rc in RCs:
if rc.lower() in signal.name.lower():
return True
for crc in CRCs:
if crc.lower() in signal.name.lower():
return True
return False
一般在项目中,ASW和com之间会有一个中间模块(Can_Wrapper)进行数据的映射。这个模块和com之间的delegation接口可根据读取dbc自动生成。达芬奇Developer也可以批量自动创建,但和ASW的接口就得手动创建了。所以这里提下生成Can_Wrapper过程中和dbc有关的部分。
接口的名称可以根据信号名再加一些特定格式,数据类型按照信号size和is_signed等定义计算出。示例代码如下:
def get_signal_dataType(signal: canmatrix.Signal): """ 计算信号生成代码的数据类型。 """ dataType = "UnknownType " if signal.is_float is True: if signal.size == 32: dataType = "float32" elif signal.size == 64: dataType = "float64" else: print(f"Not supported <{signal.size}> size of <float> data type. <{signal.__dict__}>") elif (signal.factor != 1) or (signal.offset != 0): dataType = "float32" elif signal.size == 1: dataType = "boolean" elif signal.size <= 8: if signal.is_signed: dataType = "sint8" else: dataType = "uint8" elif signal.size <= 16: if signal.is_signed: dataType = "sint16" else: dataType = "uint16" elif signal.size <= 32: if signal.is_signed: dataType = "sint32" else: dataType = "uint32" elif signal.size <= 64: if signal.is_signed: dataType = "sint64" else: dataType = "uint64" else: print(f"Unexpected datatype of signal. <{signal.__dict__}>") return f"{dataType}"
canmatrix不仅可以读取数据库文件,也可以写入,个人感觉还是比较好用的。当然其中也存在一些bug,在使用中慢慢探索并规避吧。 ^_^
欢迎批评指正和探讨交流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。