使用python将canoe的日志文件转为可文本查看的csv文件
一、说明
本文使用python实现了一种将canoe采集到的blf文件,转换为可用文本直接查看的csv文件。
二、安装依赖包
pip install cantools python-can
三、编写blf2csv.py
文件,如下:
# pip install cantools python-canimport sys
import binascii
import can
import time
from datetime import datetime# 时间戳转换为真实时间
def timestamp_convert_realtime(ts):return str(datetime.fromtimestamp(float(ts)))# 判断是接收还是发送
def can_msg_is_rx(is_rx):return 'RX' if is_rx else 'TX'# 判断是接收还是发送
def can_msg_is_fd(is_fd):return 'CanFD' if is_fd else 'Can'# 判断是接收还是发送
def can_msg_channel(channel):return 'Channel' + str(channel)def main():"""The transcoder"""with open("output.csv", mode="a+") as f:f.write("Time".ljust(35) + "Chn".ljust(13) + "ID".ljust(10) + "Name".ljust(10) + "DIR".ljust(10) + "DLC".ljust(10) + "Data\n")# 读取文件里的内容,写入新的文件with can.LogReader(sys.argv[1]) as reader:for msg in reader:row = ' '.join([timestamp_convert_realtime(repr(msg.timestamp)).ljust(30),can_msg_channel(msg.channel).ljust(5),hex(msg.arbitration_id).ljust(5),can_msg_is_fd(msg.is_fd).ljust(5),can_msg_is_rx(msg.is_rx).ljust(5),str(msg.dlc).ljust(5),(binascii.hexlify(msg.data, " ")).decode("utf-8")])f.write(row + "\n")if __name__ == "__main__":start_time = time.time()main()end_time = time.time()print(f"用时{int(end_time - start_time)}s")
三、效果如下:
执行:
python blf2csv.py 73486893_251013132203_251013132303_6695714_1.blf
上述命令执行完毕后,会在当前目录生成一个output.csv
的文件,内容如下:
Time Chn ID Name DIR DLC Data
2025-10-13 21:22:03 Channel5 0x27 CanFD RX 64 00 00 00 00 00 00 0f be a5 5f 36 c6 5d 8f 81 55 30 fe ff 33 41 fe ef ff fe ef ff 00 00 00 00 f0 ff ff b0 81 64 40 06 64 40 06 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00
2025-10-13 21:22:03 Channel1 0x27 CanFD RX 64 00 00 00 00 00 00 0f be a5 5f 36 c6 5d 8f 81 55 30 fe ff 33 41 fe ef ff fe ef ff 00 00 00 00 f0 ff ff b0 81 64 40 06 64 40 06 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00
2025-10-13 21:22:03 Channel3 0x27 CanFD RX 64 00 00 00 00 00 00 0f be a5 5f 36 c6 5d 8f 81 55 30 fe ff 33 41 fe ef ff fe ef ff 00 00 00 00 f0 ff ff b0 81 64 40 06 64 40 06 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00
2025-10-13 21:22:03 Channel6 0x152 CanFD RX 48 00 00 4c 1c 44 1c 50 9f 8b 14 00 80 e8 33 00 51 55 00 c8 90 01 f4 01 cb 01 b3 20 c0 12 14 46 49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2025-10-13 21:22:03 Channel6 0x20e CanFD RX 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.001000 Channel7 0x40 CanFD RX 48 00 00 00 00 45 21 60 80 10 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 13 ff 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.001000 Channel7 0xc0 CanFD RX 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 50 00 00 00 00 0d 02 00 00 00 00 00
2025-10-13 21:22:03.001000 Channel1 0x32 CanFD RX 48 00 00 00 00 45 21 60 80 10 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 13 ff 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.001000 Channel3 0x32 CanFD RX 48 00 00 00 00 45 21 60 80 10 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 13 ff 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.001000 Channel4 0x32 CanFD RX 48 00 00 00 00 45 21 60 80 10 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 13 ff 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.001000 Channel4 0x92 CanFD RX 24 00 00 09 03 01 1c 03 60 08 60 08 03 14 03 1c 03 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.002000 Channel5 0x605 CanFD RX 8 00 00 00 00 00 00 00 00
2025-10-13 21:22:03.002000 Channel5 0x39f CanFD RX 32 00 00 34 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9a b8 00 00 00
2025-10-13 21:22:03.002000 Channel7 0x29 CanFD RX 16 09 f0 58 01 80 8a 00 02 00 00 00 00 00 00 00 00
四、使用python实现从dbc和blf文件中解析指定的信号
- 4.1、根据blf保存的can报文,配合dbc解析信号的值,编写
can_dbc_blf.py
文件代码如下:
# pip install cantools python-canimport sys
import can
from cantools import databasedef save_output_msg(content):# print(content)with open("output.txt", mode="a+") as f:f.write(content + "\n")def parse_dbc_file(dbc_file, blf_file, specific_msg_name):# 加载DBC文件db = database.load_file(dbc_file)# 打印nodesprint(db.nodes)# 打印所有消息的 ID 和名称for message in db.messages:print(f"Message ID: {message.frame_id}, Name: {message.name}, ")# for signal in message.signals:# print(f"Name: {signal.name}")# print(f"Start bit: {signal.start}")# print(f"Bit length: {signal.length}")# print(f"byte_order: {signal.byte_order}")# print(f"Is_signed: {signal.is_signed}")# print(f"raw_initial: {signal.raw_initial}")# print(f"Raw_invalid: {signal.raw_invalid}")# print(f"conversion: {signal.conversion}")# print(f"Minimum: {signal.minimum}")# print(f"Maximum: {signal.maximum}")# print(f"Unit: {signal.unit}")# print(f"comment: {signal.comment}")# print(f"receivers: {signal.receivers}")# print(f"is_multiplexer: {signal.is_multiplexer}")# print(f"multiplexer_ids: {signal.multiplexer_ids}")# print(f"multiplexer_signal: {signal.multiplexer_signal}")# print(f"offset: {signal.offset}")# print(f"spn: {signal.spn}")# 打印指定的消息的信号信息specific_message = db.get_message_by_name(specific_msg_name)print(specific_message)# for signal in specific_message.signals:# print(signal)# 加载BLF文件blf = can.LogReader(blf_file)for can_msg in blf:if can_msg.arbitration_id == specific_message.frame_id:content = "\nDecoded ID " + hex(can_msg.arbitration_id) + ":"save_output_msg(content)# 解析 CAN 消息decoded_msg = db.decode_message(can_msg.arbitration_id, can_msg.data, decode_choices= False)## 输出解码后的信号值for signal_name, value in decoded_msg.items():content = str(signal_name) + " : " + str(value)save_output_msg(content)# print(decoded_msg)# usage: python can_dbc_blf.py xxx.dbc xxx.blf msg_name
if __name__ == "__main__":parse_dbc_file(sys.argv[1], sys.argv[2], sys.argv[3])
- 4.2、执行
python can_dbc_blf.py xxx_Draft.dbc xxx.blf VDU_3