【问题标题】:How to extract the hex value from this data type? - Python cantools如何从此数据类型中提取十六进制值? - Python cantools
【发布时间】:2020-07-23 18:48:36
【问题描述】:

我正在使用 Python cantools 库从 CAN dbc 文件中提取消息,返回的数据类型如下所示:

message('Message_10', 0x146, False, 8, None),

我需要提取第二个值0x146,并且消息名称的长度可能会发生变化,因此标准字符串切片不会始终如一地工作。

我的第一个想法是将message('Message_10', 0x146, False, 8, None), 转换为字符串,然后删除不以0x 开头的所有内容,但我怀疑有更好的方法。

这样做的目的是从 DBC 文件中提取所有 CAN ID,并创建一个字典,其中每个 CAN ID 号作为 Key。然后监控 CAN 总线并使用与 CAN 总线上的每个 CAN ID 关联的数据有效负载更新目录中的每个值。

这是我的代码的一个 sn-p,我最初试图只提取消息名称,这有效,但我需要消息 ID 0x146,作为我字典中的键,以便在我查看传入时进行比较在公交车上

有人知道如何做到这一点吗?

import cantools 

db = cantools.database.load_file('C:\\Users\\Tim\\Desktop\\dbc_file.dbc')

def can_table(db):
    messages = []
    #pprint.pprint(db.messages)
    for msg in range(0, len(db.messages)):
        x = str(db.messages[msg])
        x = x[7:]  # Remove "message"
        x = x.replace('(', '').replace(')', '').replace('\'', '')
        x = x.split(', ') # Split into list
        messages.append(x[0])  # First element is list is the message name

    message_table = {}
    # Populate values as None in dictionary 
    for i in messages:
        message_table[i]=None

    #pprint.pprint(message_table)
    return message_table

x 在调用str() 之后的示例:

"message('Message_3', 0x143, False, 8, None)"
"message('Message_2', 0x142, False, 8, None)"
"message('Message', 0x141, False, 8, None)"
"message('Message_with_long_name', 0x201, False, 8, 'comment that explains what this message does')"

dir(db.messages[1]) 的结果:

   ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bus_name', '_check_mux', '_check_signal', '_check_signal_lengths', '_check_signal_tree', '_check_signals', '_check_signals_ranges_scaling', '_codecs', '_comment', '_create_codec', '_create_signal_tree', '_cycle_time', '_dbc', '_decode', '_encode', '_frame_id', '_get_mux_number', '_is_extended_frame', '_length', '_name', '_protocol', '_send_type', '_senders', '_signal_groups', '_signal_tree', '_signals', '_strict', 'bus_name', 'comment', 'cycle_time', 'dbc', 'decode', 'encode', 'frame_id', 'get_signal_by_name', 'is_extended_frame', 'is_multiplexed', 'layout_string', 'length', 'name', 'protocol', 'refresh', 'send_type', 'senders', 'signal_choices_string', 'signal_groups', 'signal_tree', 'signal_tree_string', 'signals']

【问题讨论】:

  • 你能给x 分配str(db.messages[msg]) 后的几个例子吗?
  • @ronald 见上面的编辑
  • 看起来message 已经是一个合适的对象了。你为什么要在str(db.messages[msg]) 而不是db.messages[msg] 上工作?
  • 也许我遗漏了什么,但它不是像x.split(', ')[1] 那样简单吗?
  • 将对象转换为字符串然后解析它是完全疯狂msg 对象当然具有对应于字符串表示中存在的所有这些字段的属性;阅读cantools 文档,或至少打印dir(msg) 以查看属性的名称。

标签: python python-3.x can-bus


【解决方案1】:

第二个值是frame_id。只需执行msg.frame_id。不要将其转换为字符串。

for msg in db.messages:
    print(msg.frame_id)

从 cantools 代码中,您可以看到使用 __repr__ 方法将消息转换为字符串。

cantools.Message.__repr__

def __repr__(self):
    return "message('{}', 0x{:x}, {}, {}, {})".format(
        self._name,
        self._frame_id,
        self._is_extended_frame,
        self._length,
        "'" + self._comment + "'" if self._comment is not None else None)

【讨论】:

  • 因此,在检查上述对象时,是否应该始终在类中搜索__repr__ 函数以确定其组装方式? @shrewmouse
  • __str__ 也可以,但最好查看代码或使用 Eclipse 中的 PyDev 之类的 IDE,它会告诉您所有可用选项是什么。
  • 顺便说一句,如果您发现自己在做诸如尝试解析字符串之类的事情,那么您可能走错了路。我知道这是不得已而为之,但请让您的脑海中响起警钟。
  • 您是否知道您会推荐的 PyDev for PyCharm 之类的东西?这就是我目前工作的 IDE。是的,我认为解析是一个危险信号,很高兴它在这里得到了解决。 @shrewmouse
  • 我不使用 pycharm,但我很震惊它没有可以为您检查对象的代码完成功能。
猜你喜欢
  • 2014-02-18
  • 2018-06-24
  • 2016-07-29
  • 2022-01-25
  • 2015-05-22
  • 2013-06-22
  • 2011-07-12
  • 1970-01-01
  • 2014-12-24
相关资源
最近更新 更多