Welcome to doipclient’s documentation!¶
doipclient is a pure Python Diagnostic over IP (DoIP) client which can be used for communicating with modern ECU’s over automotive ethernet.
To discover ECU’s on your network, you can use the Vehicle Identification Announcement broadcast message (sent at powerup) as follows:
from doipclient import DoIPClient address, announcement = DoIPClient.await_vehicle_announcement() # Power cycle your ECU and wait for a few seconds for the broadcast to be # received logical_address = announcement.logical_address ip, port = address print(ip, port, logical_address) Alternatively, you can request a Vehicle Identification Response message:
from doipclient import DoIPClient address, announcement = DoIPClient.get_entity() logical_address = announcement.logical_address ip, port = address print(ip, port, logical_address) Once you have the IP address and Logical Address for your ECU, you can connect to it and begin interacting.
client = DoIPClient(ip, logical_address) print(client.request_entity_status()) You can also use UDS for diagnostic communication with the udsoncan library.
from doipclient.connectors import DoIPClientUDSConnector from udsoncan.client import Client from udsoncan.services import * uds_connection = DoIPClientUDSConnector(client) with Client(uds_connection) as uds_client: client.ecu_reset(ECUReset.ResetType.hardReset) DoIPClient¶
- class doipclient.DoIPClient(ecu_ip_address, ecu_logical_address, tcp_port=13400, udp_port=13400, activation_type=ActivationType.Default, protocol_version=2, client_logical_address=3584, client_ip_address=None, use_secure=False, auto_reconnect_tcp=False)¶
A Diagnostic over IP (DoIP) Client implementing the majority of ISO-13400-2:2019 (E).
This is a basic DoIP client which was designed primarily for use with the python-udsoncan package for UDS communication with ECU’s over automotive ethernet. Certain parts of the specification would require threaded operation to maintain the time-based state described by the ISO document. However, in practice these are rarely important, particularly for use with UDS - especially with scripts that tend to go through instructions as fast as possible.
- Parameters:
ecu_ip_address (str) – This is the IP address of the target ECU. This should be a string representing an IPv4 address like “192.168.1.1” or an IPv6 address like “2001:db8::”. Like the logical_address, if you don’t know the value for your ECU, utilize the get_entity() or await_vehicle_announcement() method.
ecu_logical_address (int) – The logical address of the target ECU. This should be an integer. According to the specification, the correct range is 0x0001 to 0x0DFF (“VM specific”). If you don’t know the logical address, either use the get_entity() method OR the await_vehicle_announcement() method and power cycle the ECU - it should identify itself on bootup.
tcp_port (int, optional) – The destination TCP port for DoIP data communication. By default this is 13400 for unsecure and 3496 when using TLS.
activation_type (RoutingActivationRequest.ActivationType, optional) – The activation type to use on initial connection. Most ECU’s require an activation request before they’ll respond, and typically the default activation type will do. The type can be changed later using request_activation() method. Use None to disable activation at startup.
protocol_version (int) – The DoIP protocol version to use for communication. Represents the version of the ISO 13400 specification to follow. 0x02 (2012) is probably correct for most ECU’s at the time of writing, though technically this implementation is against 0x03 (2019).
client_logical_address (int) – The logical address that this DoIP client will use to identify itself. Per the spec, this should be 0x0E00 to 0x0FFF. Can typically be left as default.
client_ip_address (str, optional) – If specified, attempts to bind to this IP as the source for both UDP and TCP communication. Useful if you have multiple network adapters. Can be an IPv4 or IPv6 address just like ecu_ip_address, though the type should match.
use_secure (Union[bool,ssl.SSLContext]) – Enables TLS. If set to True, a default SSL context is used. For more control, a preconfigured SSL context can be passed directly. Untested. Should be combined with changing tcp_port to 3496.
log_level (int) – Logging level
auto_reconnect_tcp (bool) – Attempt to automatically reconnect TCP sockets that were closed by peer
- Raises:
ConnectionRefusedError – If the activation request fails
ValueError – If the IPAddress is neither an IPv4 nor an IPv6 address
- class TransportType(value)¶
An enumeration.
- classmethod await_vehicle_announcement(udp_port=13400, timeout=None, ipv6=False, source_interface=None, sock=None)¶
Receive Vehicle Announcement Message
When an ECU first turns on, it’s supposed to broadcast a Vehicle Announcement Message over UDP 3 times to assist DoIP clients in determining ECU IP’s and Logical Addresses. Will use an IPv4 socket by default, though this can be overridden with the ipv6 parameter.
- Parameters:
udp_port (int, optional) – The UDP port to listen on. Per the spec this should be 13400, but some VM’s use a custom one.
timeout (float, optional) – Maximum amount of time to wait for message
ipv6 (bool, optional) – Bool forcing IPV6 socket instead of IPV4 socket
source_interface (str, optional) – Interface name (like “eth0”) to bind to for use with IPv6. Defaults to None which will use the default interface (which may not be the one connected to the ECU). Does nothing for IPv4, which will bind to all interfaces uses INADDR_ANY.
- Returns:
IP Address of ECU and VehicleAnnouncementMessage object
- Return type:
tuple
- Raises:
TimeoutError – If vehicle announcement not received in time
- close()¶
Close the DoIP client
- empty_rxqueue()¶
Implemented for compatibility with udsoncan library. Nothing useful to be done yet
- empty_txqueue()¶
Implemented for compatibility with udsoncan library. Nothing useful to be done yet
- classmethod get_entity(ecu_ip_address='255.255.255.255', protocol_version=2, eid=None, vin=None)¶
Sends a VehicleIdentificationRequest and awaits a VehicleIdentificationResponse from the ECU, either with a specified VIN, EIN, or nothing. Equivalent to the request_vehicle_identification() method but can be called without instantiation.
- Parameters:
ecu_ip_address – This is the IP address of the target ECU for unicast. Defaults to broadcast if
the address is not known. :type ecu_ip_address: str, optional :param protocol_version: The DoIP protocol version to use for communication. Represents the version of the ISO 13400
specification to follow. 0x02 (2012) is probably correct for most ECU’s at the time of writing, though technically this implementation is against 0x03 (2019).
- Parameters:
eid (bytes, optional) – EID of the Vehicle
vin (str, optional) – VIN of the Vehicle
- Returns:
The vehicle identification response message
- Return type:
- read_doip(timeout=2, transport=TransportType.TRANSPORT_TCP)¶
Helper function to read from the DoIP socket.
- Parameters:
timeout (float, optional) – Maximum time allowed for response from ECU
transport (DoIPClient.TransportType, optional) – The IP transport layer to read from, either UDP or TCP
- Raises:
IOError – If DoIP layer fails with negative acknowledgement
TimeoutException – If ECU fails to respond in time
- receive_diagnostic(timeout=None)¶
Receive a raw diagnostic payload (ie: UDS) from the ECU.
- Returns:
Raw UDS payload
- Return type:
bytearray
- Raises:
TimeoutError – No diagnostic response received in time
- reconnect(close_delay=2)¶
Attempts to re-establish the connection. Useful after an ECU reset
- Parameters:
close_delay (float, optional) – Time to wait between closing and re-opening socket
- request_activation(activation_type, vm_specific=None, disable_retry=False)¶
Requests a given activation type from the ECU for this connection using payload type 0x0005
- Parameters:
activation_type (RoutingActivationRequest.ActivationType) – The type of activation to request - see Table 47 (“Routing activation request activation types”) of ISO-13400, but should generally be 0 (default) or 1 (regulatory diagnostics)
vm_specific (int, optional) – Optional 4 byte long int
disable_retry (bool, optional) – Disables retry regardless of auto_reconnect_tcp flag. This is used by activation requests during connect/reconnect.
- Returns:
The resulting activation response object
- Return type:
- request_alive_check()¶
Request that the ECU send an alive check response
- Returns:
Alive Check Response object
- Return type:
AliveCheckResopnse
- request_diagnostic_power_mode()¶
Request that the ECU send a Diagnostic Power Mode response
- Returns:
Diagnostic Power Mode Response object
- Return type:
- request_entity_status()¶
Request that the ECU send a DoIP Entity Status Response
- Returns:
DoIP Entity Status Response
- Return type:
- request_vehicle_identification(eid=None, vin=None)¶
Sends a VehicleIdentificationRequest and awaits a VehicleIdentificationResponse from the ECU, either with a specified VIN, EIN, or nothing. :param eid: EID of the Vehicle :type eid: bytes, optional :param vin: VIN of the Vehicle :type vin: str, optional :return: The vehicle identification response message :rtype: VehicleIdentificationResponse
- send_diagnostic(diagnostic_payload, timeout=2)¶
Send a raw diagnostic payload (ie: UDS) to the ECU.
- Parameters:
diagnostic_payload (bytearray) – UDS payload to transmit to the ECU
- Raises:
IOError – DoIP negative acknowledgement received
- send_doip(payload_type, payload_data, transport=TransportType.TRANSPORT_TCP, disable_retry=False)¶
Helper function to send to the DoIP socket.
Adds the correct DoIP header to the payload and sends to the socket.
- Parameters:
payload_type (int) – The payload type (see Table 17 “Overview of DoIP payload types” in ISO-13400
transport (DoIPClient.TransportType, optional) – The IP transport layer to send to, either UDP or TCP
disable_retry (bool, optional) – Disables retry regardless of auto_reconnect_tcp flag. This is used by activation requests during connect/reconnect.
- send_doip_message(doip_message, transport=TransportType.TRANSPORT_TCP, disable_retry=False)¶
Helper function to send an unpacked message to the DoIP socket.
Packs the given message and adds the correct DoIP header before sending to the socket
- Parameters:
doip_message (object) – DoIP message object
transport (DoIPClient.TransportType, optional) – The IP transport layer to send to, either UDP or TCP
disable_retry (bool, optional) – Disables retry regardless of auto_reconnect_tcp flag. This is used by activation requests during connect/reconnect.
Encrypted Communication¶
TLS/SSL can be enabled by setting the use_secure parameter when creating an instance of DoIPClient.
client = DoIPClient( ip, logical_address, use_secure=True, # Enable encryption tcp_port=3496, ) If more control is required, a preconfigured SSL context can be provided. For instance, to enforce the use of TLSv1.2, create a context with the desired protocol version:
import ssl # Enforce use of TLSv1.2 ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) client = DoIPClient( ip, logical_address, use_secure=ssl_context, tcp_port=3496, ) Note
Since the communication is encrypted, debugging without the pre-master secret is not possible. To decrypt the TLS traffic for analysis, the pre-master secret can be dumped to a file and loaded into Wireshark. This can be done via the built-in mechanism or with sslkeylog when using Python 3.7 and earlier.