使用dbc文件解析原始can报文

使用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;


  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值