python cantools读取dbc

该博客介绍了如何使用Python的cantools库来解析DBC文件,包括根据报文ID和名称获取报文信息,以及进行CAN信号的值转换。作者提到在处理DBC资源时遇到的相关问题,如网络资源有限,源码阅读难度高等,并展示了具体的功能实现代码。
摘要由CSDN通过智能技术生成
import binascii
import struct

import cantools
from cantools.database import Message

from logutil import Logs


class DBC():
    def __init__(self, dbc_path):
        # 加载dbc文件
        self.db =cantools.db.load_file(filename=dbc_path, database_format=None,
                                        encoding="UTF-8",
                                        frame_id_mask=None, strict=False, cache_dir=None)

        self.__log = Logs()


    def get_message_by_id(self, message_id: str) -> Message:
        """
        根据报文id获取当前dbc的报文name
        :param message_id: 报文id
        :return: 报文
        """
        message = self.db.get_message_by_frame_id(int(message_id, 16))
        self.__log.debug(f"message信息:{message}")

        return message


    def get_message_by_name(self, message_name: str) -> Message:
        """
        根据报文名称获取当前dbc的报文frame_id
        :param message_name: 报文名称
        :return: 报文
        """
        message = self.db.get_message_by_name(message_name)
        self.__log.debug(f"message信息:{message}")

        return message


    def get_single_value(self, select_data: dict, value_type_is_num: bool = False) -> [dict, None]:
        """
        根据包含有message_id的字典,查询当前报文的信号表示的含义
        :param select_data: 要查询的信息,包含message_id和data
        :param value_type_is_num: 查询结果为数字还是值
        :return: 报文详情
        """

        # 在dbc中找到该信号供解析使用
        select_message = self.db.get_message_by_frame_id(int(select_data['message_id'], 16))

        message_key: bytes = b""
        for i in select_data['data']:
            message_key += struct.pack('B', i)

        if value_type_is_num:

            result = select_message.decode(message_key,
                                           decode_choices=False,  # 值为数字为 False 值为 True
                                           scaling=True,
                                           decode_containers=False)
        else:
            result = select_message.decode(message_key,
                                           decode_choices=True,  # 值为数字为 False 值为 True
                                           scaling=True,
                                           decode_containers=False)

        self.__log.debug(f"报文{select_data['message_id']}值为:{result}")

        return result

    def get_single_array(self, name: str,single_data: dict = {}):
        """
        根据报文名称和详情,返回字节形式的报文
        :param name: 要查询的报文名称
        :param single_data: 报文详情
        :return: 报文详情
        """
        # 查询报文对象
        message = self.db.get_message_by_name(name)
        # 将dbc中所有的键值对取出来
        data_orig = {}
        for i in range(len(message.signals)):
            signal = message.signals[i]
            data_orig[signal.name] = 0
        # 更新该字典键值对的值
        data_orig.update(single_data)
        # 返回字节形式
        msgdata = message.encode(data_orig, scaling=True, padding=False, strict=False)
        data_final = self.single_format(str(binascii.b2a_hex(msgdata), 'utf-8'))
        
        return data_final

    def single_format(self, single: str) -> str:
        """
        格式化信号
        :param single: 信号
        :return: 增加空格的信号
        """
        single_length: int = len(single)
        result: str = ""
        for i in range(single_length):
            if i > 0 and i%2 ==0 and i < single_length:
                result += " "+ single[i]
            else:
                result += single[i]

        return result

if __name__ == "__main__":
    dbc = DBC(".\\演示用dbc.dbc")
    print(dbc.get_single_array("message_name",{'sigle_name1': 1,'sigle_name2': 1}))
    # 00 60 00 00 00 00 00 00
    print(dbc.get_message_by_name("message_name"))
    # message('message_name', 0x001, False, 8, None)
    print(dbc.get_message_by_id("0x001"))
    print(dbc.get_single_value({"message_id": "0x001",
                                         "data": [00, 60, 00, 00, 00, 00, 00, 00]
                                         }))
    # {'sigle_name1': ' OFF ', 'sigle_name2': ' Invalid ', 'sigle_name3': ' OFF ', 'sigle_name4': 'Not Active'}

最近接受封装周立功接口的工作,在解析dbc中的CAN信号时,发现cantools相关的网络资源少,阅读源码的效率太低,而且只需要用到格式的转换。所以特此发稿。

  • 14
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Python可以使用cantools库来读取dbc文件。cantools是一个Python工具,用于解析和操作车辆通信网络数据库文件(如DBC文件)。通过使用cantools库,可以轻松地读取和解析DBC文件的CAN信号和消息定义。该库提供了丰富的API,可以帮助用户以编程方式访问和操作DBC文件的内容。要使用cantools读取dbc文件,首先需要安装cantools库。可以使用pip命令在Python环境安装cantools库。安装完成后,可以使用cantools库提供的函数和类来加载和解析dbc文件,并提取其的CAN信号和消息定义。例如,使用cantools库的dbc.load_file()函数可以加载dbc文件,并返回一个包含所有信号和消息定义的数据库对象。通过对数据库对象的操作,可以访问和获取dbc文件的信号和消息定义。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [Python DBC LIB](https://download.csdn.net/download/fz835304205/10819610)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [python cantools读取dbc](https://blog.csdn.net/qq_42450812/article/details/125300392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值