Skip to main content

与汽车诊断标准 ODX 配合使用的实用程序。

项目描述

odxtools

odxtools是一组实用程序,用于使用 ODX 标准的数据模型和相关技术处理汽车电子控制单元的诊断描述。

ODX代表“开放诊断数据交换”,主要是一种基于 XML 的文件格式,用于描述复杂分布式技术系统(通常是汽车和卡车)的电子控制单元 (ECU) 的诊断能力。ODX 是由 ASAM eV 维护的开放标准,并且由 ISO-22901进行国际标准化。

通常,ODX 用于补充 UDS 汽车诊断标准——它本身可以被认为是 OBD-II的扩展——以提供车辆 ECU 的供应商特定诊断功能的机器可处理描述。也就是说,ODX 文件描述的功能不需要是 OBD-II/UDS 的超级或子集,例如,ODX 可用于描述使用与强制要求完全不同的线路格式和约定的诊断功能通过 OBD-II/UDS。(实际上,ODX 描述的功能通常遵循这些标准。)

提供的功能odxtools包括解析和内部化 ODX 诊断数据库文件,以及对诊断请求的数据及其以 Python 方式发送到 ECU 或从 ECU 接收的响应进行解码和编码。

目录

用例

以下是一些预期的用例odxtools

  • 原型开发:直接从 python 与电子控制单元的诊断服务交互(需要接入汽车的相关 CAN 或以太网总线)
  • 生产结束校准/质量控制:初始设置和运行新生产汽车的自我诊断,以确保一切按规定工作
  • 售后:为车间实施服务功能,即根据 ISO 15031-6 (OBD II) 的法定功能以及制造商特定的例程定义测试计划
  • 原型开发(II):分析和调试使用第三方软件完成的诊断会话
  • 原型开发(三):实现与 HTTP 等更高级协议的桥接
  • odxtools面向大规模生产的开发:通过使用基于代码生成器的诊断胶水代码(如 C++ 或 rust)来加速低成本 ECU 诊断服务的实施

请注意,上面列出的一些用例目前是相当理想的。

安装

在您的系统上安装的最简单方法odxtools是通过pip

pip3 install odxtools

如果你想自己开发odxtools,你需要使用git. 第一步是克隆存储库:

cd $BASE_DIR
git clone https://github.com/mercedes-benz/odxtools

在此之后,确保安装了所有 python 依赖项:

cd $BASE_DIR/odxtools
pip3 install -r requirements.txt

接下来,构建项目并将其安装在系统上:

cd $BASE_DIR/odxtools
python3 ./setup.py build
sudo python3 ./setup.py install # <- optional

最后,更新PYTHONPATH环境变量,新克隆的模块就可以使用了:

export PYTHONPATH="$BASE_DIR/odxtools:$PYTHONPATH"

现在,您可以检查安装是否有效:

python3 -m odxtools list -a "$YOUR_PDX_FILE"

使用示例

Python 片段

  • 从文件加载 ODX 数据库somersault.pdx

    import odxtools
    
    db = odxtools.load_pdx_file("somersault.pdx", enable_candela_workarounds=False)
    
  • 列出somersault_lazyECU 的所有可用服务的名称:

    # [...]
    
    ecu = db.ecus.somersault_lazy
    print(f"Available services for {ecu.short_name}: {ecu.services}")
    
  • 确定somersault_lazyECU 用于发送和接收诊断消息的 CAN ID:

    # [...]
    
    print(f"ECU {ecu.short_name} listens for requests on CAN ID 0x{ecu.get_receive_id():x}")
    print(f"ECU {ecu.short_name} transmits responses on CAN ID 0x{ecu.get_send_id():x}")
    
  • 对ECU的session_start请求进行编码:somersault_lazy

    # [...]
    
    raw_request_data = ecu.services.session_start()
    
    print(f"Message for session start request of ECU {ecu.short_name}: {raw_request_data}")
    # -> bytearray(b'\x10\x00')
    
  • 对请求的肯定响应进行编码start_session

    # [...]
    
    raw_request_data = ecu.services.session_start()
    raw_response_data = ecu.services.session_start.positive_responses[0].encode(coded_request=raw_request_data)
    
    print(f"Positive response to session_start() of ECU {ecu.short_name}: {raw_response_data}")
    # -> bytearray(b'P')
    
  • 解码请求:

    # [...]
    
    raw_data = b"\x10\x00"
    decoded_message = ecu.decode(raw_data)
    print(f"decoded message: {decoded_message}")
    # -> decoded message: [start_session()]
    
  • 解码对请求的响应:

    # [...]
    
    raw_request_data = b"\x10\x00"
    raw_response_data = b'P'
    decoded_response = ecu.decode_response(raw_response_data, raw_request_data)
    print(f"decoded response: {decoded_response}")
    # -> decoded response: [session()]
    

交互式使用

Python REPL

python的交互式read-reval-print-loop(REPL)支持大多数平台上的tab-completion,即在这种情况下,所有数据都可以方便地交互发现,这odxtools为探索给定ECU的功能提供了一个非常方便的工具。

一个值得注意的例外是 Microsoft Windows 平台:大多数 Windows 的 Python 发行版在其 REPL 中默认不启用制表符补全。为了在这种情况下更方便,我们建议使用 ptpythonptpython 可以像任何其他 python 包一样安装,即通过pip3 install ptpython. 然后,应该开始使用 REPL

c:\odxtest>python3 "C:\Python39\Lib\site-packages\ptpython\entry_points\run_ptpython.py"

或者,pyreadline可以在通过pip3 install wheel pyreadline. 有了这个,在交互模式下的 Windows 下 python 的基本选项卡完成 应该可以工作。

命令行使用

基于 python 模块,odxtools还提供了一组命令行实用程序,用于快速交互探索。除其他外,这些实用程序允许检查 ODX/PDX 文件、侦听诊断会话等。如果odxtools在系统范围内安装,则可以使用 调用这些命令, odxtools SUBCOMMAND [PARAMS]如果存储库已通过手动克隆但尚未安装在系统范围内,调用这些实用程序的方法是通过.gitodxtoolspython3 -m odxtools SUBCOMMAND [PARAMS]

通用参数

可用的通用参数和子命令列表可以使用odxtools --help

$ odxtools --help
usage: odxtools [-h] [-c] {list,browse,snoop,find,encode-message,decode-message} ...

Utilities to interact with automotive diagnostic descriptions based on the ODX standard.

Examples:
  For printing all services use:
   odxtools list ./path/to/database.pdx --services
  For browsing the data base and encoding messages use:
   odxtools browse ./path/to/database.pdx

positional arguments:
  {list,browse,snoop,find,encode-message,decode-message}
                        Select a sub command
    list                Print a summary of automotive diagnostic files.
    browse              Interactively browse the content of automotive diagnostic files.
    snoop               Live decoding of a diagnostic session.
    find                Find & display services by hex-data, or name, can also decodes requests.
    encode-message      Encode a message. Interactively asks for parameter values.
                        This is a short cut through the browse command to directly encode a message.
    decode-message      Decode a message. Interactively asks for parameter values.
                        This is a short cut through the browse command to directly encode a message.

optional arguments:
  -h, --help            show this help message and exit
  -c, --conformant      The input file fully confirms to the standard, i.e., disable work-arounds for bugs of the CANdela tool

所有子命令都接受--help参数:

$ odxtools list --help
usage: odxtools list [-h] [-v VARIANT [VARIANT ...]] [-s [SERVICE [SERVICE ...]]] [-p] [-d] [-a] PDX_FILE
[...]

以下是当前可用的子命令的详尽列表:

list命令

list子命令用于解析.pdx数据库文件并将其内容的相关部分打印到终端。

$ odxtools list -h
usage: odxtools list [-h] [-v VARIANT [VARIANT ...]] [-s [SERVICE [SERVICE ...]]] [-p] [-d] [-a] PDX_FILE

List the content of automotive diagnostic files (*.pdx)

Examples:
  For displaying only the names of the diagnostic layers use:
    odxtools list ./path/to/database.pdx
  For displaying all content use:
    odxtools list ./path/to/database.pdx --all
  For more information use:
    odxtools list -h

positional arguments:
  PDX_FILE              path to the .pdx file

optional arguments:
  -h, --help            show this help message and exit
  -v VARIANT [VARIANT ...], --variants VARIANT [VARIANT ...]
                        Specifies which variants should be included.
  -s [SERVICE [SERVICE ...]], --services [SERVICE [SERVICE ...]]
                        Print a list of diagnostic services specified in the pdx.
                        If no service names are specified, all services are printed.
  -p, --params          Print a list of all parameters relevant for the selected items.
  -d, --dops            Print a list of all data object properties relevant for the selected items
  -a, --all             Print a list of all diagnostic services and DOPs specified in the pdx

选项--variants--services可用于指定应打印哪些服务。如果指定了该--params选项,则为所有指定的变体/服务打印消息布局,并且该--all参数打印由odxtools. 例子:

$ odxtools --conformant list $BASE_DIR/odxtools/examples/somersault.pdx --variants somersault_lazy --services do_forward_flips --params
ECU-VARIANT 'somersault_lazy' (Receive ID: 0x7b, Send ID: 0x1c8)
 num services: 5, num DOPs: 6, num communication parameters: 11.
The services of the ECU-VARIANT 'somersault_lazy' are:
 do_forward_flips <ID: somersault.service.do_forward_flips>
  Message format of a request:
           7     6     5     4     3     2     1     0
        +-----+-----+-----+-----+-----+-----+-----+-----+
      0 | sid(8 bits)                                   |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      1 | forward_soberness_check(8 bits)               |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      2 | num_flips(8 bits)                             |
        +-----+-----+-----+-----+-----+-----+-----+-----+
   Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0xba')
   Parameter(short_name='forward_soberness_check', type='VALUE', semantic=None, byte_position=1, bit_length=8, dop_ref='somersault.DOP.soberness_check')
    DataObjectProperty('soberness_check', category='LINEAR', internal_type='A_UINT32', physical_type='A_UINT32')
   Parameter(short_name='num_flips', type='VALUE', semantic=None, byte_position=2, bit_length=8, dop_ref='somersault.DOP.num_flips')
    DataObjectProperty('num_flips', category='LINEAR', internal_type='A_UINT32', physical_type='A_UINT32')
  Number of positive responses: 1
  Message format of a positive response:
           7     6     5     4     3     2     1     0
        +-----+-----+-----+-----+-----+-----+-----+-----+
      0 | sid(8 bits)                                   |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      1 | num_flips_done(8 bits)                        |
        +-----+-----+-----+-----+-----+-----+-----+-----+
   Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0xfa')
   Parameter(short_name='num_flips_done', type='MATCHING-REQUEST-PARAM', semantic=None, byte_position=1)
    Request byte position = 2, byte length = 1
  Number of negative responses: 1
  Message format of a negative response:
           7     6     5     4     3     2     1     0
        +-----+-----+-----+-----+-----+-----+-----+-----+
      0 | sid(8 bits)                                   |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      1 | rq_sid(8 bits)                                |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      2 | reason(8 bits)                                |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      3 | flips_successfully_done(8 bits)               |
        +-----+-----+-----+-----+-----+-----+-----+-----+
   Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0x7f')
   Parameter(short_name='rq_sid', type='MATCHING-REQUEST-PARAM', semantic=None, byte_position=1)
    Request byte position = 0, byte length = 1
   Parameter(short_name='reason', type='VALUE', semantic=None, byte_position=2, bit_length=8, dop_ref='somersault.DOP.error_code')
    DataObjectProperty('error_code', category='LINEAR', internal_type='A_UINT32', physical_type='A_UINT32')
   Parameter(short_name='flips_successfully_done', type='VALUE', semantic=None, byte_position=3, bit_length=8, dop_ref='somersault.DOP.num_flips')
    DataObjectProperty('num_flips', category='LINEAR', internal_type='A_UINT32', physical_type='A_UINT32')

browse命令

browse子命令使用 PyInquirer以交互方式浏览.pdx文件的数据库。例如,使用 browse子命令,您可以选择 ECU 和服务,而不会向终端发送垃圾邮件:

$ odxtools --conformant browse $BASE_DIR/odxtools/examples/somersault.pdx
? Select a Variant.  somersault_lazy
ECU-VARIANT 'somersault_lazy' (Receive ID: 0x7b, Send ID: 0x1c8)
? The variant somersault_lazy offers the following services. Select one!  do_forward_flips
? This service offers the following messages.  Request: do_forward_flips
             7     6     5     4     3     2     1     0
          +-----+-----+-----+-----+-----+-----+-----+-----+
        0 | sid(8 bits)                                   |
          +-----+-----+-----+-----+-----+-----+-----+-----+
        1 | forward_soberness_check(8 bits)               |
          +-----+-----+-----+-----+-----+-----+-----+-----+
        2 | num_flips(8 bits)                             |
          +-----+-----+-----+-----+-----+-----+-----+-----+
     Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0xba')
     Parameter(short_name='forward_soberness_check', type='VALUE', semantic=None, byte_position=1, bit_length=8, dop_ref='somersault.DOP.soberness_check')
      DataObjectProperty('soberness_check', category='LINEAR', internal_type='A_UINT32', physical_type='A_UINT32')
     Parameter(short_name='num_flips', type='VALUE', semantic=None, byte_position=2, bit_length=8, dop_ref='somersault.DOP.num_flips')
      DataObjectProperty('num_flips', category='LINEAR', internal_type='A_UINT32', physical_type='A_UINT32')
[...]

snoop命令

snoop子命令可用于解码跟踪或当前正在运行的诊断会话:

# create a socketcan `vcan0` interface
sudo ip link add dev vcan0 type vcan
sudo ip link set vcan0 up

# start the snooping on vcan0
odxtools --conformant snoop -c vcan0 --variant "somersault_lazy" $BASE_DIR/odxtools/examples/somersault.pdx

# on a different terminal, run the diagnostic session
$BASE_DIR/odxtools/examples/somersaultlazy.py -c vcan0

snoop 命令将输出以下内容:

$ odxtools --conformant snoop -c vcan0 --variant "somersault_lazy" $BASE_DIR/odxtools/examples/somersault.pdx
Decoding messages on channel vcan0
Tester: do_forward_flips(forward_soberness_check=18, num_flips=1)
 -> 7fba7f (bytearray(b'\x7f\xba\x7f'), 3 bytes)
Tester: start_session()
 -> session()
Tester: do_forward_flips(forward_soberness_check=18, num_flips=1)
 -> grudging_forward(num_flips_done=bytearray(b'\x01'))
Tester: do_forward_flips(forward_soberness_check=35, num_flips=1)
 -> flips_not_done(rq_sid=bytearray(b'\xba'), reason=0, flips_successfully_done=0)
Tester: do_forward_flips(forward_soberness_check=18, num_flips=3)
 -> grudging_forward(num_flips_done=bytearray(b'\x03'))
Tester: do_forward_flips(forward_soberness_check=18, num_flips=50)
 -> flips_not_done(rq_sid=bytearray(b'\xba'), reason=1, flips_successfully_done=6)

find命令

find子命令可用于通过十六进制请求或通过 cli 的部分名称来查找服务及其相关信息。

此外,它还可以解码十六进制请求并显示映射到服务的参数。

$ odxtools find $BASE_DIR/odxtools/examples/somersault.pdx -D 10 00


=====================================
somersault_lazy, somersault_assiduous
=====================================


 session_start <ID: somersault.service.session_start>
  Message format of a request:
           7     6     5     4     3     2     1     0  
        +-----+-----+-----+-----+-----+-----+-----+-----+
      0 | sid (8 bits)                                  |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      1 | id (8 bits)                                   |
        +-----+-----+-----+-----+-----+-----+-----+-----+
   Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0x10')
   Parameter(short_name='id', type='CODED-CONST', semantic=None, byte_position=1, bit_length=8, coded_value='0x0')
  Number of positive responses: 1
  Message format of a positive response:
           7     6     5     4     3     2     1     0  
        +-----+-----+-----+-----+-----+-----+-----+-----+
      0 | sid (8 bits)                                  |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      1 | can_do_backward_flips (8 bits)                |
        +-----+-----+-----+-----+-----+-----+-----+-----+
   Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0x50')
   Parameter(short_name='can_do_backward_flips', type='VALUE', semantic=None, byte_position=1, bit_length=8, dop_ref='somersault.DOP.boolean')
    DataObjectProperty('boolean', category='TEXTTABLE', internal_type='A_UINT32', physical_type='A_UNICODE2STRING')
  Number of negative responses: 1
  Message format of a negative response:
           7     6     5     4     3     2     1     0  
        +-----+-----+-----+-----+-----+-----+-----+-----+
      0 | sid (8 bits)                                  |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      1 | rq_sid (8 bits)                               |
        +-----+-----+-----+-----+-----+-----+-----+-----+
      2 | response_code (8 bits)                        |
        +-----+-----+-----+-----+-----+-----+-----+-----+
   Parameter(short_name='sid', type='CODED-CONST', semantic=None, byte_position=0, bit_length=8, coded_value='0x7f')
   Parameter(short_name='rq_sid', type='MATCHING-REQUEST-PARAM', semantic=None, byte_position=1)
    Request byte position = 0, byte length = 1
   Parameter(short_name='response_code', type='VALUE', semantic=None, byte_position=2, bit_length=8, dop_ref='somersault.DOP.error_code')
    DataObjectProperty('error_code', category='IDENTICAL', internal_type='A_UINT32', physical_type='A_UINT32')

Decoded Request('start_session'):
	sid: 16
	id: 0

odxtools find $BASE_DIR/odxtools/examples/somersault.pdx -d 10 00将显示相同的信息,而无需解码请求,-s <name>并可用于通过部分名称查找服务。

测试

包含的单元测试可以通过

python -m unittest tests/test_*.py

静态类型检查器可以通过

python3 -m mypy --ignore-missing-imports odxtools

贡献

我们欢迎任何贡献。如果你想为这个项目做出贡献,请阅读贡献指南

行为守则

请阅读我们的行为准则 ,因为它是我们互动的基础。

执照

该项目在MIT 许可证下获得许可

提供者信息

有关提供商的信息,请访问https://mbition.io/en/home/index.html 。

注意:在将程序用于生产用途之前,请采取所有必要的预防措施,例如针对您的特定用途测试和验证程序。该程序仅针对我们自己的用例进行了测试,可能与您的不同。

致谢

这项工作包括对 由德国联邦经济事务和气候行动部资助 的项目SofDCar (19S21002) 的研究。

执照

该项目在MIT 许可证下获得许可

项目详情