Underlying protocol (Connections)

Basics

Since UDS is an application layer protocol, it must be used over a data transport protocol. The current industry mostly uses ISO-TP protocol (ISO-15765) over CAN bus (ISO-11898).

Controller Area Network (CAN) protocol is a link layer protocol that sends data over small chunks of 8 bytes. ISO-TP is a transport protocol that allow the transmission of larger frames, usually 4095 bytes maximum although the 2016 version of the standard uses sizes defined over 32bits, which would theoretically allow frames of 4GB.

ISO-TP has been designed to be used for UDS. The current ISO-15765 protocol comes in 4 parts. ISO-15765-2 tells how to transmit large frames and ISO-15765-3 defines how to map the ISO-TP fields to a UDS message.

This project does not implement any communication protocol below the UDS layer, but provides a standard interface to interact with them.


How to

Access to the underlying protocol is done through a Connection object. A user can define his own Connection object by inheriting the BaseConnection object and implementing the abstract method.

The main interfaces to use with the Connection object are:

BaseConnection.send(data, timeout=None)[source]

Sends data to the underlying transport protocol

Parameters:
  • data (bytes, Request, Response) – The data or object to send. If a Request or Response is given, the value returned by get_payload() will be sent.

  • timeout (float | None) –

Returns:

None

Return type:

None

BaseConnection.wait_frame(timeout=None, exception=False)[source]

Waits for the reception of a frame of data from the underlying transport protocol

Parameters:
  • timeout (int) – The maximum amount of time to wait before giving up in seconds

  • exception (bool) – Boolean value indicating if this function may return exceptions. When True, all exceptions may be raised, including TimeoutException When False, all exceptions will be logged as DEBUG and None will be returned.

Returns:

Received data

Return type:

bytes or None


Available Connections

Some connections are already avaialble and can be imported from the udsoncan.connections modules. Each of these connections are meant to address a specific use case.

PythonIsoTpConnection

class udsoncan.connections.PythonIsoTpConnection(isotp_layer, name=None)[source]

Sends and receives data using a can-isotp Python module which is a Python implementation of the IsoTp transport protocol which can be coupled with python-can module to interract with CAN hardware

can-isotp must be installed in order to use this connection.

See an example

Parameters:
  • isotp_layer (isotp.TransportLayer) – The IsoTP Transport layer object coming from the isotp module.

  • name (string) – This name is included in the logger name so that its output can be redirected. The logger name will be Connection[<name>]

SyncAioIsotpConnection

class udsoncan.connections.SyncAioIsotpConnection(rx_id, tx_id, name=None, *args, **kwargs)[source]

A wrapper for aioisotp sync variant

aioisotp must be installed in order to use this connection.

See an example

Parameters:
  • rxid (int) – The reception CAN id

  • txid (int) – The transmission CAN id

  • name (string) – This name is included in the logger name so that its output can be redirected. The logger name will be Connection[<name>]

  • args (list) – Optional parameters list passed to aioisotp binding method.

  • kwargs (dict) – Optional parameters dictionary passed to aioisotp binding method.

  • rx_id (int) –

  • tx_id (int) –

Warning

This connection is based on aioisotp which is no longer actively maintained by its author. The protocol uses streams rather than datagrams and it still has some issues. However, it has good performance on Windows.

SocketConnection

class udsoncan.connections.SocketConnection(sock, bufsize=4095, name=None)[source]

Sends and receives data through a socket.

Parameters:
  • sock (socket.socket) – The socket to use. This socket must be bound and ready to use. Only send() and recv() will be called by this Connection

  • bufsize (int) – Maximum buffer size of the socket, this value is passed to recv()

  • name (string) – This name is included in the logger name so that its output can be redirected. The logger name will be Connection[<name>]

IsoTPSocketConnection

class udsoncan.connections.IsoTPSocketConnection(interface, address, name=None, tpsock=None, **kwargs)[source]

Sends and receives data through an ISO-TP socket. Makes cleaner code than SocketConnection but offers no additional functionality. The can-isotp module must be installed in order to use this connection

Parameters:
  • interface (string) – The can interface to use (example: can0)

  • address (isotp.Address or isotp.AsymmetricAddress) – The address used to bind the the socket. Before 1.21, txid/rxid were needed here, this has changed with v1.21

  • name (string) – This name is included in the logger name so that its output can be redirected. The logger name will be Connection[<name>]

  • tpsock (isotp.socket) – An optional ISO-TP socket to use instead of creating one.

QueueConnection

class udsoncan.connections.QueueConnection(name=None, mtu=4095)[source]

Sends and receives data using 2 Python native queues.

  • MyConnection.fromuserqueue : Data read from this queue when wait_frame is called

  • MyConnection.touserqueue : Data written to this queue when send is called

Parameters:
  • mtu (int) – Optional maximum frame size. Messages will be truncated to this size

  • name (string) – This name is included in the logger name so that its output can be redirected. The logger name will be Connection[<name>]

J2534Connection

class udsoncan.connections.J2534Connection(windll, rxid, txid, name=None, debug=False, *args, **kwargs)[source]

Sends and receives data through a J2534 Interface. A windows DLL and a J2534 interface must be installed in order to use this connection

Parameters:
  • windll (str) – The path to the windows DLL for the J2534 interface (example: ‘C:/Program Files{x86}../../openport 2.0/op20pt32.dll’)

  • rxid (int) – The reception CAN id

  • txid (int) – The transmission CAN id

  • name (string) – This name is included in the logger name so that its output can be redirected. The logger name will be Connection[<name>]

  • debug (boolean) – This will enable windows debugging mode in the dll (see tactrix doc for additional information)

  • args (list) – Optional parameters list (Unused right now).

  • kwargs (dict) – Optional parameters dictionary Unused right now).


Defining a new Connection

If all of the above Connection does not suits your needs, you can always implement your own Connection.

In order to define a new connection, 6 methods must be implemented as they will be called by the Client object.

abstract BaseConnection.open()[source]

Set up the connection object.

Returns:

None

Return type:

BaseConnection

abstract BaseConnection.close()[source]

Close the connection object

Returns:

None

Return type:

None

abstract BaseConnection.specific_send(payload, timeout=None)[source]

The implementation of the send method.

Parameters:
  • payload (bytes) – Data to send

  • timeout (float | None) –

Returns:

None

Return type:

None

abstract BaseConnection.specific_wait_frame(timeout=None)[source]

The implementation of the wait_frame method.

Parameters:

timeout (int) – The maximum amount of time to wait before giving up

Returns:

Received data

Return type:

bytes or None

abstract BaseConnection.empty_rxqueue()[source]

Empty all unread data in the reception buffer.

Returns:

None

Return type:

None

abstract BaseConnection.is_open()[source]

Tells if the connection is open.

Returns:

bool

Return type:

bool