pip install cantools python-can
一般情况下,解析blf需要dbc文件,当然其实不用dbc也可以,只不过解析比较麻烦,推荐还是配合dbc解析,这个也是我们最常用的办法。所以要用dbc,需要先加载dbc文件,这里需要cantools,代码:
import cantools
import can
dbc_file = r"C:\Users\master01\Downloads\blf_conf\FS04通用_TBOX(1).dbc"
dbc = cantools.db.load_file(dbc_file)
加载完dbc文件,就可以解析blf文件了,代码
f = r"C:\Users\master01\Downloads\blfdata\问题blf\1.17-9-10.blf"
log_data = can.BLFReader(f)
for msg in log_data:
print(msg)
打印结果是这样的
Timestamp: 1673917200.026000 ID: 0301 S Rx DL: 8 1d b0 41 54 07 02 00 00 Channel: 0
Timestamp: 1673917200.026000 ID: 070b S Rx DL: 8 00 c8 0c b6 24 b8 24 b8 Channel: 0
Timestamp: 1673917200.028000 ID: 0322 S Rx DL: 8 00 00 00 00 00 00 03 00 Channel: 0
Timestamp: 1673917200.126000 ID: 030d S Rx DL: 8 00 14 00 00 00 00 00 00 Channel: 0
Timestamp: 1673917200.126000 ID: 0320 S Rx DL: 8 06 b1 00 00 00 00 07 00 Channel: 0
Timestamp: 1673917200.127000 ID: 0708 S Rx DL: 8 00 48 00 48 00 08 00 32 Channel: 0
Timestamp: 1673917200.129000 ID: 0712 S Rx DL: 8 00 06 81 0d 21 05 00 00 Channel: 0
Timestamp: 1673917200.271000 ID: 1821a7c1 X Rx DL: 8 02 2f 00 00 00 00 00 00 Channel: 0
Timestamp: 1673917200.321000 ID: 0110 S Rx DL: 8 05 36 16 67 00 09 20 6b Channel: 0
Timestamp: 1673917200.322000 ID: 0111 S Rx DL: 8 16 5d 00 00 d4 00 20 bf Channel: 0
Timestamp: 1673917200.322000 ID: 0112 S Rx DL: 8 49 32 00 10 00 16 6d 4c Channel: 0
Timestamp: 1673917200.326000 ID: 0300 S Rx DL: 8 00 3a c2 f8 00 00 00 00 Channel: 0
Timestamp: 1673917200.326000 ID: 0710 S Rx DL: 8 00 00 00 00 00 00 00 00 Channel: 0
Timestamp: 1673917200.427000 ID: 0709 S Rx DL: 8 0e 02 0e b0 4a 0c ff fe Channel: 0
Timestamp: 1673917200.427000 ID: 070a S Rx DL: 8 11 51 1f fd 46 de 1c 83 Channel: 0
Timestamp: 1673917200.428000 ID: 0711 S Rx DL: 8 02 df 00 09 02 d5 00 d4 Channel: 0
Timestamp: 1673917200.438000 ID: 0308 S Rx DL: 8 03 22 0a 3c 0a 00 00 2a Channel: 0
Timestamp: 1673917200.550000 ID: 03a1 S Rx DL: 8 00 00 06 b1 00 00 15 00 Channel: 0
Timestamp: 1673917200.550000 ID: 03a2 S Rx DL: 8 00 00 00 00 00 00 05 00 Channel: 0
Timestamp: 1673917200.633000 ID: 0270 S Rx DL: 8 00 67 67 00 00 00 00 a2 Channel: 0
Timestamp: 1673917200.638000 ID: 0307 S Rx DL: 8 41 14 03 c0 36 00 00 03 Channel: 0
Timestamp: 1673917200.638000 ID: 0309 S Rx DL: 8 1c 1c 1c 1c 1c 1c c3 50 Channel: 0
Timestamp: 1673917200.655000 ID: 03a0 S Rx DL: 8 06 b1 00 00 00 00 15 00 Channel: 0
Timestamp: 1673917200.657000 ID: 030a S Rx DL: 8 00 00 00 00 00 00 00 00 Channel: 0
可以发现,时间戳解析出来了,其它的数据都是16进制,没法直接看,当然我们如果熟悉blf格式,可以自己把数据还原出来,但是既然已经用第三方库,我们当然就不用自己解析了,而且仔细观察一下即可发现,之前的加载dbc并没有用上,所以这时一个重要的函数登场了,那就是dbc.decode_message(id,data),具体代码如下
decoded = {}
for msg in logdata:
try:
dec = dbc.decode_message(msg.arbitration_id, msg.data)
if dec:
for key, data in dec.items():
if key not in decoded:
decoded[key] = []
decoded[key].append([msg.timestamp, data])
except:
pass
因为我这里是最后把数据解析出来转成mf4了,所以构建了一个decoded字典,每个key里记一个信号,熟悉mf4的应该知道,mf4里每个信号主要包含两部分,一个是时间戳,一个是数据,有了这两个,我们就可以创建mf4文件了,最后放上创建mf4的代码
from asammdf import MDF,Signal
sigs = []
for k,v in decoded.items():
timestamps = [i[0] for i in v]
data = [i[1] for i in v]
s = Signal(data,timestamps,name=k)
sigs.append(s)
mdf = MDF()
mdf.append(sigs)
mdf.save("xx.mf4",overwrite=True)
这样就实现了blf文件的解析与转换,当然,转换的格式很自由,只要熟悉相应的格式,比如csv,hdf5,xlsx,json,pickle都可以,因为我们已经拿到原始数据了,保存成什么格式就很简单了。