Python中的高级/抽象CAN总线接口

Python中的高级/抽象CAN总线接口,python,python-3.x,hardware,can-bus,Python,Python 3.x,Hardware,Can Bus,我正在使用python中的canbus(Pcan基本api),并希望使其更易于使用 许多设备/模块通过总线连接。他们都被允许发送数据,如果发生碰撞,最低ID将获胜 数据以具有ID、SubID和hexvalues的帧组织 为了说明我试图解决的问题,想象一个信号的振幅 读取帧发送到的值的步骤 QuestionID QuestionSUBID QuestionData 如果没有具有更高优先级(=lowerID)的消息,则答案将写入总线: AnswerID AnswerSubID AnswerDa

我正在使用python中的canbus(Pcan基本api),并希望使其更易于使用

许多设备/模块通过总线连接。他们都被允许发送数据,如果发生碰撞,最低ID将获胜

数据以具有ID、SubID和hexvalues的帧组织

为了说明我试图解决的问题,想象一个信号的振幅

读取帧发送到的值的步骤

  • QuestionID QuestionSUBID QuestionData
如果没有具有更高优先级(=lowerID)的消息,则答案将写入总线:

  • AnswerID AnswerSubID AnswerData
因为任何模块/设备都可以写入总线,所以您事先不知道下一步会得到哪个答案。设置值的方式相同,只是ID不同。因此,对于上述示例,振幅应为:

  • 4与读/写问题/答案关联的ID和子ID
  • 此外,必须指定/存储数据的长度(0-8)
  • 由于数据都是十六进制值,因此必须指定解析器以获得人类可读的值(例如十进制表示的电压)
  • 要存储此信息,我使用嵌套的dict:

    parameters = {'Parameter_1': {'Read': {'question_ID': ID, 
                                           'question_SUBID': SubID,
                                           'question_Data': hex_value_list,
                                           'answer_ID': ...,
                                           'answer_subID': ..., 
                                           'answer_parser': function},
                                   'Write': {'ID': ...,
                                             'SubID': ...,
                                             'parser' ..., 
                                             'answer_ID': ...,
                                             'answer_subID': ...}},
                   'Parameter_2': ... }} 
    
    有很多工具可以显示何时设置了哪个值,但对于硬件控制,参数的读取顺序并不相关,只要它们是最新的。因此,可能的解决方案的一部分是将整个流量存储在一个dict of dict中:

    busdata = {'firstID' : {'first_subID': {'data': data, 
                                            'timestamp': timestamp},
                          'second_subID': {'data': data, 
                                            'timestamp': timestamp},
    
                          }, 
                secondID': ...}
    
    由于总线的性质,我得到了很多其他设备询问的答案-总线已经满了-这些不应该被忽略,因为它们可能是我接下来需要的值,并且没有必要创建额外的流量-我可能会使用带有到期日期的时间戳,但到目前为止我没有考虑太多

    这是可行的,但使用起来很糟糕。一般来说,我想我会有大约300个参数。最终的目标是通过(pyqt)Gui控制设备,读取一些值,如序列号,同时运行测量任务

    因此,最大的问题是如何定义一个更易于访问和理解的数据结构?我期待着任何关于清洁设计的建议

    主要目标是摆脱整个基于消息的aproach

    编辑:我的目标是摆脱整个基于CAN特定消息的方法:

    我假设我需要一个线程进行通信,它应该:

  • 读取缓冲区并更新我的变量
  • 发送请求(消息)以获取其他值/变量
  • 定期发送一些值
  • 因此,通过gui,我希望能够:

  • 按名称获取参数-->发送带参数名称的字符串
  • 设置参数信号-->str(名称)、值(如gui中所显示)
  • 定期获取值-->名称、间隔、持续时间(10秒或无限)
  • 线程必须:

  • 将总线上的所有数据记录到内部存储器中
  • 通过从name、value和read生成消息来处理请求,直到获得结果
  • 发送周期性信号
  • 我想要实际硬件的设计理念:

    • 我想到的解决方案是上述参数
    对于内部存储,我考虑了总线数据目录

    我还是不知道怎么做:

  • 将数据从总线线程传递到gui(所有值与新的/请求的值)
  • 如何在pyqt中使用信号和插槽实现它
  • 在内部存储数据(dict of dict或一些新的更好的想法)
  • 如果这个设计是一个好的选择
  • 我可能不太理解你的问题。。。也许你可以用更多的细节来更新它,使用这个库将为你带来一个网络线程,给你一个传入消息的缓冲队列。该库支持PCAN接口等

    然后,您将创建一个中间件层,将这些
    can.Message
    类型转换并路由为pyqt信号。将其视为事件/信号的一对多来源

    我会使用另一个控制器来负责向总线发送消息。它可以执行诸如从总线请求定期测量以及由gui驱动的按需请求等任务

    关于在内部存储数据,这实际上取决于您的编程风格和复杂性。我见过这样的项目,每个CAN消息都有自己的类


    最后,排队是你的朋友

    同意@Hardbyte的使用。太棒了

    至于应用层之间的消息传递,我很幸运——您可以将模块设置为基于事件的,从canbus消息事件一直到更新UI或其他任何内容


    对于数据存储/持久化,我将消息放入SQLite,并并行(使用模式)将数据传递到IoT中心(via)。

    创建一个类,将其抽象出来。。。canbus完全基于消息包,所以我认为您无法消除它。。。但你当然可以把它抽象出来……是的,当然。也许我说得够清楚了。问题是如何实现这一点。我考虑了使用适当的getter和setter的属性,但我仍然需要数据的内部表示。谢谢。我采取了一种非常类似的方法,仍然试图将其抽象为mvc模式。Python只能使用,与peak systems示例相同。我通过将Unicode转换成字节字符串修复了他们的代码。你说的“Python只能与之一起工作”是什么意思?在任何系统中,都必须确保向总线发送字节。
    class MySimpleCanBus:
          def parse_message(self,raw_message):
              return MyMessageClass._create(*struct.unpack(FRAME_FORMAT,msg))
          def recieve_message(self,filter_data):
              #code to recieve and parse a message(filtered by id)
              raw = canbus.recv(FRAME_SIZE)
              return self.parse_message(raw)
          def send_message(msg_data):
              # code to make sure the message can be sent and send the message
              return self.recieve_message()
    
    class MySpecificCanBus(MySimpleCanBus):
        def get_measurement_reading():
             msg_data = {} #code to request a measurement
             return self.send_message(msg_data)
        def get_device_id():
             msg_data = {} # code to get device_id
             return self.send_message(msg_data)