Diagnostic Messages¶
In this chapter, you will find information about messages
subpackage implementation. It contains code that
enables creation of entities that carry UDS data and helps to describe theirs transmission.
- In implementation we distinguish following entities that carry diagnostic data:
UDS Message - carries application data (diagnostic service) on upper layers (layers 5-7 of UDS OSI model), it might also be called Application Protocol Data Unit (A_PDU)
UDS Packet - packets that are exchanged between client and server during UDS Message segmentation (layers 3-4 of UDS OSI model), it might also be called Network Protocol Data Unit (N_PDU)
Bus Frame - a single frame transmitted over any bus on lower layers (layers 1-2 of UDS/bus OSI model), it carries any data that is not necessarily related to UDS communication
Additionally, you will find Transmission Attributes and UDS Data Enums chapters which contain implementation details about enums that help to describe transmission and data of aforementioned entities.
UDS Message¶
Diagnostic messages (either diagnostic requests or response messages) are called ‘UDS Messages’ in the implementation.
- In the code, the diagnostic message features are divided into two parts:
UdsMessage - storage for diagnostic message (A_PDU) attributes that could be used by a user to transmit this UDS Message on a configured bus
UdsMessageRecord - record with historic information about either received or transmitted diagnostic message
UdsMessage¶
Diagnostic messages has common specification for all buses, therefore UdsMessage
class has the only one
implementation which is the same regardless of bus used by a user. UdsMessage
is a storage
for diagnostic message attributes, therefore if you want to send any diagnostic message, you should prior create
UdsMessage
object first.
from uds.messages import UdsMessage, AddressingType
# example how to define a UDS Message
uds_message = UdsMessage(raw_message=[0x10, 0x03],
addressing=AddressingType.PHYSICAL)
# you have two attributes that you can freely change
print(uds_message.raw_message)
uds_message.raw_message = [0x3E, 0x00]
print(uds_message.raw_message)
print(uds_message.addressing)
uds_message.addressing = AddressingType.FUNCTIONAL
print(uds_message.addressing)
UdsMessageRecord¶
Historic records with information about diagnostic messages that were either received or transmitted, are stored in
objects of UdsMessageRecord
class.
from uds.messages import UdsMessageRecord, AddressingType
# usually, you would not be doing this by yourself as Client and Server features are meant to create objects of this class
uds_message_records = UdsMessageRecord(raw_message=[0x10, 0x03],
packets_records=[uds_packet_record]) # at least one packet - instance of `AbstractUdsPacketRecord` class
# you can get attributes of the UDS Message Record object
print(uds_message_records.raw_message)
print(uds_message_records.packets_records)
print(uds_message_records.addressing)
print(uds_message_records.direction)
print(uds_message_records.transmission_end)
UDS Packet¶
- To efficiently handle UDS Packets (Network Protocol Data Units - N_PDUs), the implementation is divided into two parts:
UDS Packet Definition - storage of UDS Packet (N_PDU) attributes that could be used by a user to transmit UDS Packet on a dedicated bus
UDS Packet Record - record with historic information about either received or transmitted UDS Packet (N_PDU)
UDS Packet Definition¶
UDS Packets slightly differ for each bus, therefore abstract class (AbstractUdsPacket) is separated
out in the implementation. If you want to define UDS Packet (that might be sent later on), you should create
an object of any of concrete classes that inherits after AbstractUdsPacket
class.
Currently following classes are implemented to handle creation of new UDS Packets (N_PDUs):
AbstractUdsPacket¶
AbstractUdsPacket
class contains common implementation of all UDS Packet types. You should never call
AbstractUdsPacket
class directly, therefore in the example below ConcreteUdsPacket
(as a concrete implementation of UDS Packet for desired bus) is used instead:
from uds.messages import AddressingType, ConcreteUdsPacket
# you can define UDS Packet (N_PDU)
packet = ConcreteUdsPacket(raw_data=[0x02, 0x3E, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55],
addressing=AddressingType.PHYSICAL)
# you can get attributes of the packet object
print(packet.raw_data)
print(packet.addressing)
print(packet.packet_type) # this will only work for concrete UDS Packet implementation
# you can change values of UDS Packet object attributes
packet.raw_data = (0x03, 0x22, 0xF1, 0x84, 0x00, 0x00, 0x00, 0x00)
packet.addressing = "Functional"
UDS Packet Record¶
UDS Packet Record is a record with historic data of UDS Packet (N_PDU) that was either received or transmitted. Due to difference in structure of UDS Packets for various buses, abstract class (AbstractUdsPacketRecord) is separated out in the implementation.
- Currently following classes are implemented to store historic data of UDS Packets (N_PDUs):
AbstractUdsPacketRecord¶
AbstractUdsPacketRecord
class contains common implementation of all UDS Packets records for all buses.
You should never call AbstractUdsPacketRecord
class directly, therefore in the example below
ConcreteUdsPacketRecord
(as a concrete implementation of UDS Packet record for a certain bus) is used instead:
from uds.messages import TransmissionDirection, ConcreteUdsPacketRecord
# usually, you would not be doing this by yourself as Transport Interface feature is meant to create objects of this class
packet_record = ConcreteUdsPacketRecord(frame=some_frame,
direction=TransmissionDirection.RECEIVED,
...) # ... represents additional arguments that are required by a concrete class
# you can get attributes of the UDS Packet Record object
print(packet_record.frame)
print(packet_record.direction)
print(packet_record.raw_data)
print(packet_record.packet_type)
print(packet_record.addressing)
print(packet_record.transmission_time)
UDS Packet Type¶
Network Protocol Control Information determines value of UDS Packet (N_PDU) type (e.g. whether this is the only/the first/following UDS Packet). Due to differences in UDS specifications for various buses, abstract class (AbstractPacketType) is separated out in the implementation.
- Currently following enums with UDS Packet Type (N_PCI) values are implemented:
AbstractPacketType¶
An empty enum with helper methods. It is meant to be parent class for all concrete UDS Packet Type enums classes.
from uds.messages import AbstractPacketType
# you can check if value is member of AbstractPacketType enum
AbstractPacketType.is_member(value_to_check) # returns True if value is member, False otherwise
AbstractPacketType.validate_member(value_to_check) # raises an exception if value is not a member of the enum
# you can add a new enum member
AbstractPacketType.add_member(name="NEW_NPCI_NAME", value=0x0)
Transmission Attributes¶
Transmission attributes are used to unambiguously describe UDS transmission.
- Following enums are available:
TransmissionDirection¶
TransmissionDirection
enum is used to determine whether diagnostic data entity (message/packet/frame) was
either received or transmitted.
from uds.messages import TransmissionDirection
TransmissionDirection.RECEIVED
TransmissionDirection.TRANSMITTED
AddressingType¶
AddressingType
is used to determine type of transmission (one/many recipient(s) and communication model).
from uds.messages import AddressingType
AddressingType.PHYSICAL
AddressingType.FUNCTIONAL
AddressingType.BROADCAST # in fact, this is FUNCTIONAL addressing with broadcast communication used, but it was separated to distinguish this case
UDS Data Enums¶
- There are following enums that contains information related to UDS Messages data:
RequestSID¶
Enum with all known Service Identifier (SID) values that might be used in a request message.
from uds.messages import RequestSID
# you can check if value is valid request sid
RequestSID.is_request_sid(value_to_check)
# you can check whether value is enum member
RequestSID.is_member(value_to_check) # returns True if value is member, False otherwise
RequestSID.validate_member(value_to_check) # raises an exception if value is not a member of the enum
ResponseSID¶
Enum with all known Response Service Identifier (RSID) values that might be used in a response message.
from uds.messages import ResponseSID
# you can check if value is valid request sid
ResponseSID.is_response_sid(value_to_check)
# you can check whether value is enum member
ResponseSID.is_member(value_to_check) # returns True if value is member, False otherwise
ResponseSID.validate_member(value_to_check) # raises an exception if value is not a member of the enum
NRC¶
Enum with all known Negative Response Code (NRC) values that might be used in a negative response message.
from uds.messages import NRC
# you can check whether value is NRC enum member
NRC.is_member(value_to_check) # returns True if value is member, False otherwise
NRC.validate_member(value_to_check) # raises an exception if value is not a member of the enum
# you can add a new enum member
NRC.add_member(name="NAME_FOR_NEW_MEMBER", value=0x00)