SAE J1939堆栈实现

j1939的Python项目详细描述


针对python的can-sae j1939标准的新实现。

警告:当前此项目处于alpha状态!有些功能不能完全工作!

如果您遇到问题或认为堆栈的行为不正常,请执行 毫不犹豫地开一张票或写一封电子邮件。 pullrequests当然更受欢迎!

该项目使用python-can包来支持多个硬件驱动程序。 在编写时,支持的接口是

  • 可通过串行连接
  • 串行/SLcan上的can
  • ixxat虚拟can接口
  • Kvaser的canlib
  • Neovi接口
  • 镍罐
  • PCAN基本API
  • socketcan
  • USB2can接口
  • 矢量
  • 虚拟
  • IScan

概述

SAE J1939 CAN网络由多个电子控制单元(ECU)组成。 每个ecu可以有一个或多个控制器应用程序(cas)。每个CA都有 总线上自己的(唯一的)地址。此地址可以在 地址声明过程或设置为固定值。在后一种情况下,ca 必须在公共汽车上公布地址以检查是否有空。

SAE J1939网络中的CAN信息称为协议数据单元(PDU)。 这个定义并不完全正确,但足够接近于pdu 作为can信息。

功能

  • 一个电子控制单元(ecu)可以容纳多个控制器应用程序(ca)
  • 根据SAE J1939/81命名的电子控制单元(CA)
  • (在建)符合SAE J1939/81的全功能地址申请程序
  • 完全支持根据SAE J1939/21发送和接收
    • 消息打包和重新组装(最多1785字节)
      • 传输协议传输数据(tp.td)
      • 传输协议通信管理(tp.cm)
    • 多包广播
      • 广播通告消息(tp.bam)
  • (在建)请求(全局和特定)
  • (在建)正确的超时和截止日期处理
  • (在建)几乎完成测试覆盖率

安装

一旦您的发行版中提供了该软件包,就可以轻松地做到:

$ pip install j1939

同时,您可以下载Wheel软件包并发出以下命令:

$ pip install j1939-0.1.0.dev1-py2.py3-none-any.whl

或者使用:

$ git clone https://github.com/benkfra/j1939.git
$ cd j1939
$ pip install .

如果您想在使用时更改代码,请克隆它,然后将其安装到develop mode

$ git clone https://github.com/benkfra/j1939.git
$ cd j1939
$ pip install -e .

快速启动

要简单地接收总线上的所有传递(公共)消息,您可以订阅ecu对象。

importloggingimporttimeimportcanimportj1939logging.getLogger('j1939').setLevel(logging.DEBUG)logging.getLogger('can').setLevel(logging.DEBUG)defon_message(pgn,data):"""Receive incoming messages from the bus

    :param int pgn:
        Parameter Group Number of the message
    :param bytearray data:
        Data of the PDU
    """print("PGN {} length {}".format(pgn,len(data)))defmain():print("Initializing")# create the ElectronicControlUnit (one ECU can hold multiple ControllerApplications)ecu=j1939.ElectronicControlUnit()# Connect to the CAN bus# Arguments are passed to python-can's can.interface.Bus() constructor# (see https://python-can.readthedocs.io/en/stable/bus.html).# ecu.connect(bustype='socketcan', channel='can0')# ecu.connect(bustype='kvaser', channel=0, bitrate=250000)ecu.connect(bustype='pcan',channel='PCAN_USBBUS1',bitrate=250000)# ecu.connect(bustype='ixxat', channel=0, bitrate=250000)# ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)# ecu.connect(bustype='nican', channel='CAN0', bitrate=250000)# subscribe to all (global) messages on the busecu.subscribe(on_message)time.sleep(120)print("Deinitializing")ecu.disconnect()if__name__=='__main__':main()

一个更复杂的例子,其中ca类被重载以包含其自己的功能:

importloggingimporttimeimportcanimportj1939logging.getLogger('j1939').setLevel(logging.DEBUG)logging.getLogger('can').setLevel(logging.DEBUG)classOwnCaToProduceCyclicMessages(j1939.ControllerApplication):"""CA to produce messages

    This CA produces simulated sensor values and cyclically sends them to
    the bus with the PGN 0xFEF6 (Intake Exhaust Conditions 1).
    """def__init__(self,name,device_address_preferred=None):# old fashion calling convention for compatibility with Python2j1939.ControllerApplication.__init__(self,name,device_address_preferred)defstart(self):"""Starts the CA
        (OVERLOADED function)
        """# add our timer eventself._ecu.add_timer(0.500,self.timer_callback)# call the super class functionreturnj1939.ControllerApplication.start(self)defstop(self):"""Stops the CA
        (OVERLOADED function)
        """self._ecu.remove_timer(self.timer_callback)defon_message(self,pgn,data):"""Feed incoming message to this CA.
        (OVERLOADED function)
        :param int pgn:
            Parameter Group Number of the message
        :param bytearray data:
            Data of the PDU
        """print("PGN {} length {}".format(pgn,len(data)))deftimer_callback(self,cookie):"""Callback for sending the IEC1 message

        This callback is registered at the ECU timer event mechanism to be
        executed every 500ms.

        :param cookie:
            A cookie registered at 'add_timer'. May be None.
        """# wait until we have our device_addressifself.state!=j1939.ControllerApplication.State.NORMAL:# returning true keeps the timer event activereturnTruepgn=j1939.ParameterGroupNumber(0,0xFE,0xF6)data=[j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8,# Particulate Trap Inlet Pressure (SPN 81)j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8,# Boost Pressure (SPN 102)j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8,# Intake Manifold 1 Temperature (SPN 105)j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8,# Air Inlet Pressure (SPN 106)j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8,# Air Filter 1 Differential Pressure (SPN 107)j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_16_ARR[0],# Exhaust Gas Temperature (SPN 173)j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_16_ARR[1],j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8,# Coolant Filter Differential Pressure (SPN 112)]# SPN 105, Range -40..+210# (Offset -40)receiverTemperature=30data[2]=receiverTemperature+40self.send_message(6,pgn.value,data)# returning true keeps the timer event activereturnTruedefmain():print("Initializing")# create the ElectronicControlUnit (one ECU can hold multiple ControllerApplications)ecu=j1939.ElectronicControlUnit()# Connect to the CAN bus# Arguments are passed to python-can's can.interface.Bus() constructor# (see https://python-can.readthedocs.io/en/stable/bus.html).# ecu.connect(bustype='socketcan', channel='can0')# ecu.connect(bustype='kvaser', channel=0, bitrate=250000)ecu.connect(bustype='pcan',channel='PCAN_USBBUS1',bitrate=250000)# ecu.connect(bustype='ixxat', channel=0, bitrate=250000)# ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)# ecu.connect(bustype='nican', channel='CAN0', bitrate=250000)# ecu.connect('testchannel_1', bustype='virtual')# compose the name descriptor for the new caname=j1939.Name(arbitrary_address_capable=0,industry_group=j1939.Name.IndustryGroup.Industrial,vehicle_system_instance=1,vehicle_system=1,function=1,function_instance=1,ecu_instance=1,manufacturer_code=666,identity_number=1234567)# create derived CA with given NAME and ADDRESSca=OwnCaToProduceCyclicMessages(name,128)# add CA to the ECUecu.add_ca(controller_application=ca)# by starting the CA it starts the address claiming procedure on the busca.start()time.sleep(120)print("Deinitializing")ca.stop()ecu.disconnect()if__name__=='__main__':main()

学分

这个实现最初的灵感来自CANopen project of Christian Sandberg。 谢谢你的出色工作!

有关SAE J1939的大部分信息摘自 Copperhill technologies从我在j1939多年的工作经验来看,当然:—)

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Android使用两个后台服务错误   解压缩HTTPInputStream时,java GZIPInputStream过早关闭   javax和javax的区别是什么。网ssl。密钥库和服务器。ssl。为SpringBoot应用程序指定密钥库时的密钥库属性   java生成两个JPanel,而我只需要一个   java深度链接从play store安装应用程序时获取数据   java 安卓应用程序在退出时未正确释放蓝牙   java正确使用setCellValueFactory   java开放JdbcTemplate连接处于只读模式?   使用Spring MVC创建服务时发生java错误   JavaFX获取安装在计算机中的特定应用程序的版本   SecureRandom的安全问题:PRNG在java 1.5中不一致   windows我可以创建一个独立的。带Inno设置的Java应用程序的exe安装程序?   如何使用JavaServlet下载csv文件?   java从生成的缓冲图像中添加图像作为jasper中的数据记录?   java日期和时间解析