Как правильно читать сообщения J1939 из файла .asc с помощью cantools?

Я пытаюсь создать конвертер журналов 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

person Wojciech Wołujewicz    schedule 26.02.2021    source источник


Ответы (1)


класс can.ASCReader(file, base='hex') Базы: can.io.generic.BaseIOHandler Итератор сообщений CAN из файла регистрации ASC. Метаданные (комментарии, статистика шины, сообщения транспортного протокола J1939) игнорируются. Может ответить на ваш вопрос...

person richard    schedule 09.03.2021
comment
Добро пожаловать в СО! Не забудьте отформатировать свой код, окружив его тремя обратными кавычками (`) или добавив перед каждой строкой 1 отступ. - person CATboardBETA; 10.03.2021