python-udsoncan

repository·master·Indexed 20 days ago

https://github.com/pylessard/python-udsoncan

A Python 3 implementation of the Unified Diagnostic Services (UDS) protocol as defined by ISO-14229. It provides tools to interact with vehicle ECUs via transport layers like ISO-TP, allowing developers to build and interpret UDS payloads, manage diagnostic sessions, and detect malformed messages. The library includes a synchronous Client for handling request/response cycles, support for custom security algorithms, and configurable codecs for Data Identifiers (DID) and Input/Output Control (IOC).

Tokens
22.7K
Snippets
56
Records
111
Agent score
72%

What's inside python-udsoncan

  1. Overview of python-udsoncan

    master
    python-udsoncan is a Python 3 implementation of the Unified Diagnostic Services (UDS) protocol as defined by the ISO-14229 standard. It provides tools to interact with UDS servers by building and interpreting UDS payloads and detecting malformed messages. It is designed for developing tester units, debugging server code, searching for security flaws, or general automotive diagnostic tasks.
  2. Understand Unified Diagnostic Services (UDS) concepts

    master

    Unified Diagnostic Services (UDS), defined by the ISO-14229 standard, is an application protocol interface used for diagnostics, debugging, and configuration of Electronic Control Units (ECUs) in road vehicles.

    Key roles in a UDS communication:

    • UDS Client: Typically a tester unit connected to a vehicle diagnostic port.
    • UDS Server: An ECU within the vehicle connected to the CAN bus.

    UDS defines message formatting and the interface for services, but the specific implementation of how a server responds to a request is left to the ECU manufacturer.

  3. How the UDS security algorithm handshake works

    master

    While UDS does not define the specific mathematical algorithm used for security, it defines the protocol for the key exchange. The process follows a request/response pattern consisting of two main exchanges:

    1. Request Seed: The client requests a seed for a specific security level (identified by a number). The seed acts as a nonce to prevent replay attacks.
    2. Compute Key: The client receives the seed and computes a key using a manufacturer-defined algorithm.
    3. Send Key: The client sends the computed key to the server. If the server verifies the key, the security level is unlocked and a positive response is sent.
  4. How UDS sessions and security levels work

    master

    UDS communication involves managing both the current session and the current security level.

    Sessions

    When a client connects, the server typically assigns it a default session. In this session, only a limited set of services (like reading DTCs) are available.

    • A client can switch to other sessions using the DiagnosticSessionControl service.
    • The ECU manufacturer can define up to 32 additional sessions beyond the default.
    • Switching sessions is a way to change the available service set, not a security mechanism itself.

    Security Levels

    A security level is a status that grants access to restricted features (services, subfunctions, or specific values) by providing a security key.

    • There can be up to 64 security levels.
    • Unlocking process: You cannot unlock security levels in the default session. You must first switch to a non-default session that enables the SecurityAccess service.
    • Expiration: Security privileges often expire after a short period. To maintain an active session and keep security levels unlocked, the client must send keepalive messages using the TesterPresent service.
  5. How the UDS Client works

    master

    The udsoncan.client.Client is a synchronous client designed to handle a single request/response cycle at a time. It simplifies interaction with the Services object by automating repetitive tasks and providing error handling.

    When you request a service, the client automatically performs the following sequence:

    1. Builds the request payload.
    2. Calls the connection's empty_rxqueue method to clear stale messages.
    3. Sends the request.
    4. Waits for a response (respecting the configured timeout).
    5. Interprets and validates the response data.
    6. Returns the response object.

    This abstraction allows the client to detect usage errors and malformed server responses automatically.

  6. Work with DTC (Diagnostic Trouble Codes) and its sub-components

    master

    The udsoncan.Dtc class and its associated components are used to manage Diagnostic Trouble Codes.

    Key sub-components include:

    • udsoncan.Dtc.Status: Represents the status of a DTC.
    • udsoncan.Dtc.DtcClass: Represents the class of a DTC.
    • udsoncan.Dtc.Severity: Represents the severity level of a DTC.
    • udsoncan.Dtc.Format: Handles the formatting of DTCs.
    • udsoncan.Dtc.FunctionalGroupIdentifiers: Manages functional group identifiers related to DTCs.
  7. Understand the four layers of UDS interaction

    master

    The python-udsoncan library allows you to interact with UDS (Unified Diagnostic Services) at different levels of abstraction, ranging from raw byte manipulation to high-level client methods:

    1. Raw Connection: Manually sending and receiving binary payloads via a connection object.
    2. Request and Responses: Using Request and Response objects to wrap payloads, providing basic service and code identification.
    3. Services: Using service-specific objects (e.g., services.RoutineControl) to generate requests and interpret responses, including automatic parsing of service-specific data (like control_type_echo).
    4. Client: Using the high-level Client class, which provides named methods (e.g., client.start_routine()) and handles validation of echoed data automatically.
    # Level 4: High-level Client usage
    try:
       response = client.start_routine(routine_id=0x1234)
       print('Success!')
    except Exception:
       print('Start of routine 0x1234 failed')
  8. How Connections work in python-udsoncan

    master

    Since UDS is an application layer protocol, it requires a data transport protocol (like ISO-TP over CAN) to function. python-udsoncan does not implement the underlying communication protocols itself, but instead provides a standard Connection interface to interact with them.

    Users interact with the underlying protocol through a Connection object. This abstraction allows the Client object to remain agnostic of whether you are using a CAN bus, a socket, or a custom transport layer.

  9. How UDS services work: Crafting and Parsing requests/responses

    master

    Each UDS service is represented by a class extending BaseService. Services follow a two-step pattern for communication:

    1. Crafting a request: Use the service's make_request method. This returns a Request instance containing the payload. You then send this payload via your Connection object.
    2. Parsing a response: After receiving a payload from the connection, wrap it in a Response object using Response.from_payload(payload). Then, call the service's interpret_response method. This parses the raw response.data and populates the response.service_data property with an instance of the service's nested ResponseData class.

    This pattern ensures that raw byte payloads are converted into structured, typed Python objects.

    # Crafting a request
    req = SomeService.make_request(param1, param2) 
    my_connection.send(req.get_payload())
    
    # Parsing a response
    payload = my_connection.wait_frame(timeout=1)
    response = Response.from_payload(payload) 
    print('Raw data : %s' % response.data)
    SomeService.interpret_response(response, param1, param2) 
    print('Interpreted data : field1 : %s, field2 : %s' % (response.service_data.field1, response.service_data.field2))
  10. How UDS services and subfunctions work

    master

    Functionality in UDS is organized into services. A service is a type of request that includes specific parameters.

    Common examples of services include:

    • Reading Diagnostic Trouble Codes (DTCs)
    • Writing Data By Identifier (setting vehicle-specific configuration)
    • Input/Output Control By Identifier (overriding IOs)
    • ECU Reset

    Subfunctions: Many services include subfunctions, which are identified by the first byte of the service payload. For example, the ECUReset service uses a subfunction to specify the type of reset requested, such as a 'hard reset' (power cycle) or a 'soft reset' (firmware restart).

  11. Implement a custom security algorithm for SecurityAccess

    master

    To use the SecurityAccess service, you must provide a security_algo callable in the client configuration. This function implements the specific security logic required by your ECU.

    Signature Requirements: Starting from v1.12, parameters are passed by name. The function must accept:

    • level (int): The requested security level.
    • seed (bytes): The seed provided by the server.
    • params (any): The value provided via the security_algo_params configuration key.

    Returns:

    • bytes: The calculated security key.

    Example configuration:

    config = {
        'security_algo': my_algorithm_function,
        'security_algo_params': {'key': 'some_value'}
    }