使用dbc文件解析原始can报文
意义:
1 解析一条原始can报文里面各个信号的原始值和物理值。自动化脚本比手动去查找起始位计算偏移方便。
2 解析多条原始can报文里面各个信号的原始值和物理值。自动化脚本比手动去查找起始位计算偏移方便。
1. 目前支持dbc解析开源库:
c++ dbcppp
python cantools
2. cantools的安装
pip install cantools
3. cantools说明文档
https://cantools.readthedocs.io/en/latest/
4. 不错的入门文档:
https://blog.csdn.net/PlutoZuo/article/details/133637800
5. 源代码演示:
import cantools
g_dbc_file_name = "test_v0.dbc"
def xl_dbc_show(dbc_file_name):
#1. 加载DBC文件
#db = cantools.database.load_file(dbc_file_name)
db = cantools.db.load_file(dbc_file_name)
#2. 遍历节点
for node in db.nodes:
print("Node name: ", node.name)
print("Node comment: ", node.comment)
print("\n")
#3. 遍历消息
for message in db.messages:
print("Message name: ", message.name)
print("Message id: ", message.frame_id)
print("Message length: ", message.length)
print("Message senders: ", message.senders)
print("Message comment: ", message.comment)
print("\n")
#4.遍历DBC中的所有消息的所有信号
'''
# 这个只能遍历message,这一个消息的型号
for signal in message.signals:
print("Signal name: ", signal.name)
print("Signal start bit: ", signal.start)
print("Signal length: ", signal.length)
print("Signal byte order: ",signal.byte_order)
'''
for message in db.messages:
print(f"Message: {message.name}, ID: {message.frame_id}\n")
#访问dbc中的信号
for signal in message.signals:
print(f"__repr__: {signal}")
print(f"name: {signal.name}")
print(f"start: {signal.start}, length: {signal.length}")
print(f"byte_order: {signal.byte_order}, is_signed: {signal.is_signed}")
print(f"raw_initial: {signal.raw_initial}")
print(f"scaleme: {signal.conversion.scale}, offset: {signal.conversion.offset}")
print(f"minimum: {signal.minimum}, maximum: {signal.maximum}")
print(f"unit: {signal.unit}")
print(f"is_multiplexer: {signal.is_multiplexer}, multiplexer_ids: {signal.multiplexer_ids}")
print(f"choices: {signal.choices}, spn: {signal.spn}")
print(f"comments: {signal.comments}\n")
print("\n")
#案例1
def xl_dbc_recv_analysis_example_1():
# 解析CAN消息
db = cantools.db.load_file(g_dbc_file_name)
#input_dbc_data = b'\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
input_dbc_data = [0x12,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00]
input_dbc_id = 0x100
decoded_msg = db.decode_message(frame_id_or_name=dbc_id, data=bytes(dbc_data))
print("xl_dbc_recv_analysis", decoded_msg)
#案例2
def xl_dbc_recv_analysis_example_2():
# 解析CAN消息
db = cantools.database.load_file(g_dbc_file_name)
dbc_data = [0x12,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00]
dbc_id = 0x100
can_message = bytes(dbc_data)
message = db.get_message_by_frame_id(dbc_id)
decoded_message = message.decode(can_message)
# 输出解码后的消息
print("xl_dbc_recv_analysis_second", decoded_message)
RLCR_01 = decoded_message['RLCR_01']
RLCR_02 = decoded_message['RLCR_02']
print(f"RLCR_01: {RLCR_01}, RLCR_02: {RLCR_02}")
#案例3
def xl_dbc_send_encode_example_3():
# 组包CAN消息
db = cantools.db.load_file(g_dbc_file_name)
# 编码CAN消息
input_dbc_encode_data = {'RLCR_01': 1,
'RLCR_02': 2,
'RLCR_03': 3,
'RLCR_04': 4,
'RLCR_05': 5,
'RLCR_06': 6,
'RLCR_07': 7,
'RLCR_08': 8,}
dbc_id = "CRTB_100"
encoded_msg = db.encode_message(frame_id_or_name=dbc_id, data=input_dbc_encode_data)
print("xl_dbc_send_encode_example_3:", encoded_msg)
################################################################################
############################下面是使用api ######################################
################################################################################
def xl_dbc_recv_analysis(dbc_file_name, dbc_id, dbc_data):
# 加载CAN数据库
db = cantools.db.load_file(dbc_file_name)
# 解析CAN消息
decoded_message = db.decode_message(frame_id_or_name=dbc_id, data=bytes(dbc_data))
#print("xl_dbc_recv_analysis", decoded_message)
return decoded_message
def xl_dbc_recv_analysis_second(dbc_file_name, dbc_id, dbc_data):
# 加载 .dbc 文件
db = cantools.database.load_file(dbc_file_name)
# 使用数据库和帧ID找到消息的定义
message = db.get_message_by_frame_id(dbc_id)
# 解码消息
can_message = bytes(dbc_data)
decoded_message = message.decode(can_message)
# 输出解码后的消息
print("xl_dbc_recv_analysis_second", decoded_message)
return decoded_message
def xl_dbc_send_encode(dbc_file_name, dbc_id, dbc_data):
# 加载CAN数据库
db = cantools.db.load_file(dbc_file_name)
encoded_msg = db.encode_message(frame_id_or_name=dbc_id, data=dbc_data)
print("xl_dbc_send_encode:", encoded_msg)
return encoded_msg
def xl_dbc_show_signals(dbc_file_name, signals_name):
db = cantools.db.load_file(dbc_file_name)
for message in db.messages:
#print(f"Message: {message.name}, ID: {message.frame_id}\n")
for signal in message.signals:
#print(f"__repr__: {signal}")
if (signal.name != signals_name):
continue
print(f"name: {signal.name}, start: {signal.start}, len: {signal.length}")
print(f"byte_order: {signal.byte_order}, is_signed: {signal.is_signed}, raw_initial: {signal.raw_initial}")
print(f"scaleme: {signal.conversion.scale}, offset: {signal.conversion.offset}, min: {signal.minimum}, max: {signal.maximum}\n")
def xl_dbc_show_message(dbc_file_name, message_name):
db = cantools.db.load_file(dbc_file_name)
for message in db.messages:
if (message_name == message.name):
print(f"Message: {message.name}, ID: {message.frame_id}\n")
def xl_dbc_TEST():
#打开的文件名及路径
g_dbc_file_name = "test_v0.dbc"
#1. show this dbc
#xl_dbc_show(g_dbc_file_name)
#Can original message parsing
dbc_id = 0x100
dbc_data = [0x12,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00]
message = xl_dbc_recv_analysis(g_dbc_file_name, dbc_id, dbc_data)
print("RLCR_01:", message["RLCR_01"])
print("RLCR_02:", message["RLCR_02"])
#Can original message parsing
dbc_id = 0x101
dbc_data = [0x13,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00]
message = xl_dbc_recv_analysis_second(g_dbc_file_name, dbc_id, dbc_data)
print("RLCR_09:", message["RLCR_09"])
print("RLCR_10:", message["RLCR_10"])
#Can signal encoding is used to send messages
dbc_encode_data = {'RLCR_01': 1,
'RLCR_02': 2,
'RLCR_03': 3,
'RLCR_04': 4,
'RLCR_05': 5,
'RLCR_06': 6,
'RLCR_07': 7,
'RLCR_08': 8,}
dbc_id = "RCTB_100"
message = xl_dbc_send_encode(g_dbc_file_name, dbc_id, dbc_encode_data)
print("xl_dbc_send_encode:", message)
if __name__ == "__main__":
#1. 打开的文件名及路径
g_dbc_file_name = "test_v1.dbc"
#2. Can original message parsing
dbc_id = "RCTB_100"
dbc_data = [0x0A,0x0B,0x10,0x0C, 0x00,0x00,0x00,0x12, 0x34,0x00,0x00,0x00, 0x00,0x00,0x00,0x00]
print("dbc_id:", dbc_id)
print("dbc_data:", dbc_data)
message = xl_dbc_recv_analysis(g_dbc_file_name, dbc_id, dbc_data)
for name, value in message.items():
print(f"name: {name}, value: {value}")
#xl_dbc_show_signals(g_dbc_file_name, name)
#print("RLCR_01:", message["RLCR_01"])
#print("RLCR_02:", message["RLCR_02"])
import cantools
导入的开源库
如下是示例代码部分说明,主要为了好理解cantools库的使用,不看也行。
def xl_dbc_show(dbc_file_name):
打印dbc文件的节点,消息,信息等信息。
def xl_dbc_recv_analysis_example_1():
测试解析原始can报文案例1。
def xl_dbc_recv_analysis_example_2():
测试解析原始can报文案例2。
def xl_dbc_send_encode_example_3():
测试组包发送的can报文案例。
def xl_dbc_show_signals(dbc_file_name, signals_name):
测试dbc遍历信号函数。
def xl_dbc_show_message(dbc_file_name, message_name):
测试dbc遍历消息函数。
def xl_dbc_TEST():
测试dbc主函数。
实际会用到的几个接口如下:
def xl_dbc_recv_analysis(dbc_file_name, dbc_id, dbc_data):
实际使用的解析原始can报文接口函数1。
def xl_dbc_recv_analysis_second(dbc_file_name, dbc_id, dbc_data):
实际使用的解析原始can报文接口函数2。
def xl_dbc_send_encode(dbc_file_name, dbc_id, dbc_data):
实际使用的组包原始can报文接口函数。
if name == “main”:
实际运行代码的入口。
g_dbc_file_name = “test_v1.dbc”
表示加载的dbc文件。
dbc_id = “RCTB_100”
dbc的id,可以之间使用ID的名字,也可以是ID数字。
dbc_data = [0x0A,0x0B,0x10,0x0C, 0x00,0x00,0x00,0x12, 0x34,0x00,0x00,0x00, 0x00,0x00,0x00,0x00]
要解析的原始can报文。
6.测试结果:
7.案例里面使用的dbc文件:(CSDN,传文件很麻烦,所以这里直接把文件的内容拷贝出来了,命名为“test_v1.dbc” 这个名字就行)
VERSION "Version 20210304
20210504,PT1-2,@HLW: 1、modify MRR_AEBTargetDecel maxvalue(16-> 15.994187);
2、add message 0x50E ADAS_NM;
20210618, add debug message (0x1D8~0x1DE)(0x140~0x15F) "
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: CR_1 CR_2 CR_3 CR_4
BO_ 256 RCTB_100: 16 Vector__XXX
SG_ RLCR_06 : 47|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_04 : 31|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_07 : 55|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_03 : 23|8@0+ (0.1,20) [0|0] "" Vector__XXX
SG_ RLCR_05 : 39|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_08 : 56|16@1+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_02 : 15|8@0+ (1,10) [0|0] "" Vector__XXX
SG_ RLCR_01 : 7|8@0+ (0.1,0) [0|0] "" Vector__XXX
BO_ 257 RCTB_101: 16 CR_3
SG_ RLCR_14 : 47|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_12 : 31|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_15 : 55|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_11 : 23|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_13 : 39|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_16 : 63|16@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_10 : 15|8@0+ (1,0) [0|0] "" Vector__XXX
SG_ RLCR_09 : 7|8@0+ (1,0) [0|0] "" Vector__XXX
BA_DEF_ BO_ "GenMsgFastOnStart" INT 0 65535;
BA_DEF_ BU_ "NmAsrCanMsgReducedTime" INT 500 818;
BA_DEF_ BU_ "NmAsrCanMsgCycleOffset" INT 0 635;
BA_DEF_ BO_ "NmMessage" ENUM "No","Yes";
BA_DEF_ "NmAsrWaitBusSleepTime" INT 0 5000;
BA_DEF_ "NmAsrRepeatMessageTime" INT 0 3000;
BA_DEF_ "NmAsrCanMsgCycleTime" INT 0 1000;
BA_DEF_ BU_ "NmStationAddress" HEX 0 255;
BA_DEF_ BO_ "DiagState" ENUM "No","Yes";
BA_DEF_ BO_ "GenMsgDelayTime" INT 0 1000;
BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes";
BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 65535;
BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 100000;
BA_DEF_ BO_ "GenSigTimeoutTime_DUT" INT 0 100000;
BA_DEF_ BO_ "TpTxIndex" INT 0 10000;
BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes";
BA_DEF_ BU_ "ILUsed" ENUM "No","Yes";
BA_DEF_ BU_ "NodeLayerModules" STRING ;
BA_DEF_ BU_ "TpOwnSystemEcuNumber" HEX 0 255;
BA_DEF_ BU_ "TpNodeMessageCount" HEX 0 255;
BA_DEF_ BU_ "TpNodeBaseAddress" HEX 0 65535;
BA_DEF_ BU_ "NmAsrNodeIdentifier" HEX 0 255;
BA_DEF_ BU_ "DiagStationAddress" HEX 0 255;
BA_DEF_ BU_ "NmAsrNode" ENUM "No","Yes";
BA_DEF_ "Baudrate" INT 0 0;
BA_DEF_ "NmType" STRING ;
BA_DEF_ "ILTxTimeout" INT 0 65535;
BA_DEF_ "NmAsrTimeoutTime" INT 0 65535;
BA_DEF_ "NmAsrBaseAddress" HEX 1280 2047;
BA_DEF_ "NmAsrMessageCount" INT 0 256;
BA_DEF_ BO_ "DiagResponse" ENUM "No","Yes";
BA_DEF_ BO_ "DiagRequest" ENUM "No","Yes";
BA_DEF_ BU_ "DiagNode" ENUM "No","Yes";
BA_DEF_ SG_ "Remark" STRING ;
BA_DEF_ SG_ "GenSigTimeoutTime" INT 0 65536;
BA_DEF_ SG_ "EventCommandSignal" ENUM "No","Yes";
BA_DEF_ SG_ "GatewayedSignals" ENUM "No","Yes";
BA_DEF_ SG_ "GenSigTimeoutValue" FLOAT 0 0;
BA_DEF_ SG_ "GenSigStartValue" FLOAT 0 0;
BA_DEF_ SG_ "GenSigInvalidValue" FLOAT 0 0;
BA_DEF_ SG_ "GenSigInactiveValue" FLOAT 0 0;
BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed";
BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 0;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0;
BA_DEF_ BO_ "GenMsgSendType" ENUM "Cyclic","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed","IfActive","NoMsgSendType","NotUsed";
BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","StandardCAN_FD","ExtendedCAN_FD";
BA_DEF_ BO_ "CANFD_BRS" ENUM "0","1";
BA_DEF_ "Manufacturer" STRING ;
BA_DEF_ "Project" STRING ;
BA_DEF_ "Version" STRING ;
BA_DEF_ "Date" STRING ;
BA_DEF_ "Author" STRING ;
BA_DEF_ "DBName" STRING ;
BA_DEF_ "BusType" STRING ;
BA_DEF_ "Checker" STRING ;
BA_DEF_ "Approver" STRING ;
BA_DEF_REL_ BU_SG_REL_ "GenSigSuprvRespSubValue" INT 0 0;
BA_DEF_REL_ BU_SG_REL_ "GenSigSuprvResp" ENUM "None","TimeoutFlag","TimeoutDefaultValue";
BA_DEF_DEF_ "GenMsgFastOnStart" 0;
BA_DEF_DEF_ "NmAsrCanMsgReducedTime" 575;
BA_DEF_DEF_ "NmAsrCanMsgCycleOffset" 0;
BA_DEF_DEF_ "NmMessage" "No";
BA_DEF_DEF_ "NmAsrWaitBusSleepTime" 2000;
BA_DEF_DEF_ "NmAsrRepeatMessageTime" 3000;
BA_DEF_DEF_ "NmAsrCanMsgCycleTime" 500;
BA_DEF_DEF_ "NmStationAddress" 255;
BA_DEF_DEF_ "DiagState" "No";
BA_DEF_DEF_ "GenMsgDelayTime" 0;
BA_DEF_DEF_ "GenMsgILSupport" "No";
BA_DEF_DEF_ "GenMsgNrOfRepetition" 0;
BA_DEF_DEF_ "GenMsgStartDelayTime" 0;
BA_DEF_DEF_ "GenSigTimeoutTime_DUT" 0;
BA_DEF_DEF_ "TpTxIndex" 0;
BA_DEF_DEF_ "NmAsrMessage" "No";
BA_DEF_DEF_ "ILUsed" "Yes";
BA_DEF_DEF_ "NodeLayerModules" "oseknm01.dll,osek_tp.dll,CANoeILNLVector.dll";
BA_DEF_DEF_ "TpOwnSystemEcuNumber" 0;
BA_DEF_DEF_ "TpNodeMessageCount" 0;
BA_DEF_DEF_ "TpNodeBaseAddress" 65535;
BA_DEF_DEF_ "NmAsrNodeIdentifier" 6;
BA_DEF_DEF_ "DiagStationAddress" 0;
BA_DEF_DEF_ "NmAsrNode" "No";
BA_DEF_DEF_ "Baudrate" 500000;
BA_DEF_DEF_ "NmType" "NmPwrTrainChery";
BA_DEF_DEF_ "ILTxTimeout" 40;
BA_DEF_DEF_ "NmAsrTimeoutTime" 2000;
BA_DEF_DEF_ "NmAsrBaseAddress" 1536;
BA_DEF_DEF_ "NmAsrMessageCount" 128;
BA_DEF_DEF_ "DiagResponse" "No";
BA_DEF_DEF_ "DiagRequest" "No";
BA_DEF_DEF_ "DiagNode" "No";
BA_DEF_DEF_ "Remark" "";
BA_DEF_DEF_ "GenSigTimeoutTime" 0;
BA_DEF_DEF_ "EventCommandSignal" "No";
BA_DEF_DEF_ "GatewayedSignals" "No";
BA_DEF_DEF_ "GenSigTimeoutValue" 0;
BA_DEF_DEF_ "GenSigStartValue" 0;
BA_DEF_DEF_ "GenSigInvalidValue" 0;
BA_DEF_DEF_ "GenSigInactiveValue" 0;
BA_DEF_DEF_ "GenSigSendType" "NoSigSendType";
BA_DEF_DEF_ "GenMsgCycleTimeFast" 0;
BA_DEF_DEF_ "GenMsgCycleTime" 0;
BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType";
BA_DEF_DEF_ "VFrameFormat" "StandardCAN";
BA_DEF_DEF_ "CANFD_BRS" "0";
BA_DEF_DEF_ "Manufacturer" "Vector";
BA_DEF_DEF_ "Project" "";
BA_DEF_DEF_ "Version" "";
BA_DEF_DEF_ "Date" "";
BA_DEF_DEF_ "Author" "";
BA_DEF_DEF_ "DBName" "";
BA_DEF_DEF_ "BusType" "";
BA_DEF_DEF_ "Checker" "";
BA_DEF_DEF_ "Approver" "";
BA_DEF_DEF_REL_ "GenSigSuprvRespSubValue" 0;
BA_DEF_DEF_REL_ "GenSigSuprvResp" "None";
BA_ "NmAsrWaitBusSleepTime" 5000;
BA_ "NmAsrCanMsgCycleTime" 200;
BA_ "NmAsrRepeatMessageTime" 1000;
BA_ "NmAsrBaseAddress" 1280;
BA_ "NmType" "NmAsr";
BA_ "BusType" "CAN FD";
BA_ "Approver" "Approver";
BA_ "Checker" "Checker";
BA_ "Author" "Author";
BA_ "Date" "2020-11-16";
BA_ "Version" "Version";
BA_ "Project" "Project";
BA_ "NmAsrTimeoutTime" 1000;
BA_ "NmAsrMessageCount" 256;
BA_ "DBName" "T28_Private_CAN";
BA_ "GenMsgILSupport" BO_ 256 1;
BA_ "CANFD_BRS" BO_ 256 1;
BA_ "VFrameFormat" BO_ 256 14;
BA_ "GenMsgILSupport" BO_ 257 1;
BA_ "CANFD_BRS" BO_ 257 1;
BA_ "VFrameFormat" BO_ 257 14;
BA_ "GenSigStartValue" SG_ 256 RLCR_08 0;
BA_ "GenSigStartValue" SG_ 256 RLCR_02 0;