Odxtools
odxtools is a collection of utilities to interact with the diagnostic functionality of automotive electronic control units using python
Install / Use
/learn @mercedes-benz/OdxtoolsREADME
odxtools
odxtools is a set of utilities for working with diagnostic
descriptions of automotive electronic control units using the data
model and the associated technologies of the ODX standard.
ODX stands for "Open Diagnostic data eXchange" and is primarily an XML based file format to describe the diagnostic capabilities of the electronic control units (ECUs) of complex distributed technical systems (usually cars and trucks). ODX is an open standard maintained by ASAM e.V. and is also standardized internationally by ISO-22901.
Usually, ODX is used to complement the UDS automotive diagnostics standard -- which itself can be considered to be an extension of OBD-II -- to provide a machine-processable description of the vendor-specific diagnostics functionality of a vehicle's ECUs. That said, the functionality which is described by ODX files neither needs to be a super- nor a subset of OBD-II/UDS, e.g., ODX can be used to describe diagnostic functionality that uses fundamentally different wire formats and conventions than the ones mandated by OBD-II/UDS. (In practice, the ODX-described functionality usually adheres to these standards, though.)
The functionality provided by odxtools encompasses parsing and
internalizing ODX diagnostic database files as well as de- and
encoding the data of diagnostic requests and their responses
send to/received from ECUs in an pythonic manner.
Table of Contents
- Use Cases
- Installation
- Usage Examples
- Using the non-strict mode
- Interactive Usage
- Command line usage
- Testing
- Contributing
- Code of Conduct
- Provider Information
- Acknowledgements
- License
Use Cases
Here are some of the intended use cases of odxtools:
- Prototype development: Interacting with the diagnostic services of electronic control units directly from python (requires taping into the car's relevant CAN or ethernet bus)
- End-of-production calibration/quality control: Initial set up and running a self diagnosis of newly produced cars to ensure that everything works as specified
- After-sales: Implementing servicing functionality for workshops, i.e., defining test schedules based on the legally mandated functionality of ISO 15031-6 (OBD II) as well as manufacturer-specific routines
- Prototype development (II): Analyzing and debugging diagnostic sessions done using third-party software
- Prototype development (III): Implementing bridges to higher-level protocols such as HTTP
- Development for mass production: Accelerating the implementation of
diagnostic servicesfor low-cost ECUs by using
odxtools-based code generators for the diagnostic glue code on system-level languages like C++ or rust
Please be aware that some of the use cases listed above are currently rather aspirational.
Installation
The easiest way of installing odxtools on your system is via pip:
python3 -m pip install odxtools
If you want to develop odxtools itself, you need to install it from
source using git. The first step is to clone the repository:
cd $BASE_DIR
git clone https://github.com/mercedes-benz/odxtools
After this, make sure that all python dependencies are installed:
cd $BASE_DIR/odxtools
python3 -m pip install -e .
Next, you can optionally build a package and install it on the system:
cd $BASE_DIR/odxtools
python3 -m pip install --upgrade build
python3 -m build
sudo python3 -m pip install dist/odxtools-*.whl
Finally, update the PYTHONPATH environment variable and the newly
cloned module is ready to be used:
export PYTHONPATH="$BASE_DIR/odxtools:$PYTHONPATH"
Now, you can check whether the installation worked:
python3 -m odxtools list -a "$YOUR_PDX_FILE"
Usage Examples
Python snippets
-
Load an ODX database from file
somersault.pdx:import odxtools db = odxtools.load_pdx_file("somersault.pdx") -
List the names of all available services of the
somersault_lazyECU:# [...] ecu = db.ecus.somersault_lazy print(f"Available services for {ecu.short_name}: {ecu.services}") -
Determine the CAN IDs which the
somersault_lazyECU uses to send and receive diagnostic messages:# [...] print(f"ECU {ecu.short_name} listens for requests on CAN ID 0x{ecu.get_can_receive_id():x}") print(f"ECU {ecu.short_name} transmits responses on CAN ID 0x{ecu.get_can_send_id():x}") -
Encode a
session_startrequest to thesomersault_lazyECU:# [...] 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') -
Print all mutable parameters of the
session_startservice's first positive response:# [...] ecu.services.session_start.positive_responses[0].print_free_parameters_info() -
Encode the positive response to the
start_sessionrequest:# [...] raw_request_data = ecu.services.session_start() raw_response_data = ecu.services.session_start.positive_responses[0].encode(can_do_backward_flips="true", coded_request=raw_request_data) print(f"Positive response to session_start() of ECU {ecu.short_name}: {raw_response_data.hex(' ')}") # -> Positive response to session_start() of ECU somersault_lazy: 50 01 -
Decode a request:
# [...] raw_data = b"\x10\x00" decoded_message = ecu.decode(raw_data) for x in decoded_message: print(f"decoded as '{x.coding_object.short_name}': {x.param_dict}") # -> decoded as 'start_session': {'sid': 16, 'id': 0} -
Decode a response to a request:
# [...] raw_request_data = bytes.fromhex("1000") raw_response_data = bytes.fromhex("5001") decoded_response = ecu.decode_response(raw_response_data, raw_request_data) for x in decoded_response: print(f"decoded as '{x.coding_object.short_name}': {x.param_dict}") # -> decoded as 'session': {'sid': 80, 'can_do_backward_flips': 'true'}
Using the non-strict mode
By default, odxtools raises exceptions if it suspects that it cannot fulfill a requested operation correctly. For example, if the dataset it is instructed to load is detected to be not conformant with the ODX specification, or if completing the operation requires missing features of odxtools. To be able to deal with such cases, odxtools provides a "non-strict" mode where such issues are ignored, but where the results are undefined. The following snippet shows how to instruct odxtools to load a non-conforming file in non-strict mode, and after this is done, enables the safety checks again:
import odxtools
[...]
odxtools.exceptions.strict_mode = False
botched_db = odxtools.load_file("my_non-conforming_database.pdx")
odxtools.exceptions.strict_mode = True
[...]
Interactive Usage
Python REPL
python's interactive read-reval-print-loop (REPL) supports
tab-completion on most plattforms, i.e., in this case, all data can be
conveniently interactivly discovered and this makes odxtools a very
convenient tool to explore the capabilities of a given ECU.
A notable exception is the Microsoft Windows platform: Most python
distribtions for Windows do not enable tab-completion by default in
their REPL. For more convenience in such a scenario, we recommend
using
ptpython. ptpython
can be installed like any other python package, i.e., via python3 -m pip install ptpython. Then, the REPL ought to be started using
c:\odxtest>python3 "C:\Python39\Lib\site-packages\ptpython\entry_points\run_ptpython.py"
Alternatively, pyreadline can be used after installing it via
python3 -m pip install pyreadline. With this, basic
tab-completion for python under Windows in Interactive
Mode
should work.
Command line usage
Based the python module, odxtools also provides a set of command
line utilities for quick interactive explorations. Amongst others,
these utilities allow the inspection ODX/PDX files, snooping on
diagnostic sessions, etc. If odxtools is installed on a system-wide
basis, these commands can be invoked using odxtools SUBCOMMAND [PARAMS], if the repository has been manually cloned via git and
odxtools has not been installed on a system-wide basis, the way to
invoke these utilities is via python3 -m odxtools SUBCOMMAND [PARAMS].
Generic parameters
Available generic parameters and a list of subcommands can be obtained
using odxtools --help:
$ odxtools --help
usage: odxto
