【问题标题】:How to properly read J1939 messages from .asc file with cantools?如何使用 cantools 从 .asc 文件中正确读取 J1939 消息?
【发布时间】:2021-02-26 12:28:12
【问题描述】:

我正在尝试创建一个 CAN 日志转换器,从 .asc 文件到 .csv 文件(以人类可读的形式)。我有点成功。我的代码几乎适用于除 j1939.dbc 以外的任何数据库。

问题是,如果我打印出从 dbc 文件中读取的消息,我可以看到来自 j1939.dbc 的消息已读入数据库。但它无法在已处理的日志文件中找到任何这些消息。同时,我可以毫无问题地使用 Vector CANalyzer 读取相同的文件。

我想知道为什么会发生这种情况以及为什么它只影响 j1939.dbc 而不会影响其他。

我怀疑我转换这些消息的方式可能是错误的,因为它永远不会经过if msg_id in database: 行(如上所述,这些消息肯定存在,因为 Vector CANalyzer 可以很好地与它们配合使用)。

编辑:我意识到问题可能不是 cantools 而是 python-can 包,也许 can.ASCReader() 对 j1939 帧表现不佳并忽略了它们?我要调查自己,但我希望更擅长编码的人能提供帮助。

import pandas as pd
import can
import cantools
import time as t
from tqdm import tqdm
import re
import os
from binascii import unhexlify


dbcs = [filename.split('.')[0] for filename in os.listdir('./dbc/') if filename.endswith('.dbc')]
files = [filename.split('.')[0] for filename in os.listdir('./asc/') if filename.endswith('.asc')]
start = t.time() 

db = cantools.database.Database()

for dbc in dbcs:
    with open(f'./dbc/{dbc}.dbc', 'r') as f:
        db.add_dbc(f)


f_num = 1

for fname in files:
    print(f'[{f_num}/{len(files)}] Parsing data from file: {fname}')    
    log=can.ASCReader(f'./asc/{fname}.asc')
    entries = []
    all_msgs =[]


    message = {'Time [s]': ''}
    database = list(db._frame_id_to_message.keys())
    print(database)
    lines = sum(1 for line in open(f'./asc/{fname}.asc'))
    msgs = iter(log)

    try:
        for msg, i in zip(msgs, tqdm(range(lines))):

            msg = re.split("\\s+", str(msg))
            timestamp = round(float(msg[1]), 0)
            msg_id = int(msg[3], 16)

            try:
                data = unhexlify(''.join(msg[7:15]))
            except:
                continue

            if msg_id in database:
                if timestamp != message['Time [s]']:
                    entries.append(message.copy())
                    message.update({'Time [s]': timestamp})
                message.update(db.decode_message(msg_id, data))

    except ValueError:
        print('ValueError')
        
    df = pd.DataFrame(entries[1:])
    duration = t.time() - start
    df.to_csv(f'./csv/{fname}.csv', index=False)
    print(f'DONE IN {int(round(duration, 2)//60)}min{round(duration % 60, 2)}s!\n{len(df.columns)} signals extracted!')
    f_num += 1

【问题讨论】:

    标签: python canalyzer python-can


    【解决方案1】:

    class can.ASCReader(file, base='hex') 基础:can.io.generic.BaseIOHandler 来自 ASC 日志文件的 CAN 消息迭代器。元数据(cmets、总线统计、J1939 Transport 协议消息)被忽略。 可能会回答你的问题...

    【讨论】:

    • 欢迎来到 SO!请记住通过将代码用三个反引号 (`) 括起来来格式化代码,或者在每行前加 1 个缩进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 2014-05-17
    • 1970-01-01
    相关资源
    最近更新 更多