Using UDS protocol
UdsAuxiliary class (pykiso.lib.auxiliaries.udsaux.uds_auxiliary.UdsAuxiliary
) contained
in uds_auxiliary.py is the main interface between user and all the behind implemented logic.
This class defines usable keywords(methods) for scripters in order to send uds requests to the device under test (raw or configurable)…
Configuration
To configure the UDS auxiliary 3 parameters are mandatory :
odx_file_path: path to the odx formatted ecu diagnostic definition file.
Note
More information about yaml test configuration creation are available under Test Integration Framework project documentation.
Find below a complete configuration example :
auxiliaries:
uds_aux:
connectors:
com: can_channel
config:
# you can specify your odx file by using odx_file_path parameter
# and instead of using send_uds_raw method use the send_uds_config
# for a more human readable command
odx_file_path: null
request_id : 0x123
response_id : 0x321
# uds_layer parameter is not mandatory and by default the following
# values will be applied:
# transport_protocol -> CAN
# p2_can_client -> 5
# p2_can_server -> 1
uds_layer:
transport_protocol: 'CAN'
# p2_can specifies receive time outs in seconds
p2_can_client: 5
p2_can_server: 1
# tp_layer parameter is not mandatory and by default the following
# values will be applied:
# addressing_type -> NORMAL
# n_sa -> 0xFF
# n_ta -> 0xFF
# n_ae -> 0xFF
# m_type -> DIAGNOSTICS
# discard_neg_resp -> False
tp_layer:
addressing_type: 'NORMAL'
n_sa: 0xFF
n_ta: 0xFF
n_ae: 0xFF
m_type: 'DIAGNOSTICS'
discard_neg_resp: False
type: pykiso.lib.auxiliaries.udsaux.uds_auxiliary:UdsAuxiliary
connectors:
can_channel:
config:
interface : 'pcan'
channel: 'PCAN_USBBUS1'
state: 'ACTIVE'
type: pykiso.lib.connectors.cc_pcan_can:CCPCanCan
test_suite_list:
- suite_dir: test_uds
test_filter_pattern: 'test_raw_uds*.py'
test_suite_id: 1
Send UDS Raw Request
Send UDS request as list of raw bytes.
The method send_uds_raw(pykiso.lib.auxiliaries.udsaux.UdsAuxiliary.send_uds_raw()
) takes one mandatory parameter msg_to_send and one optional : timeout_in_s
The parameter msg_to_send is simply the UDS request payload which is a list of bytes.
The optional parameter timeout_in_s (by default fixed to 5 seconds) simply represent the maximum amount of time in second to wait for a response from the device under test. If this timeout is reached, the uds-auxiliary stop to acquire and log an error.
The method send_uds_raw method returns a UdsResponse
object, which is a subclass of UserList.
UserList allow to keep property of the list, meanwhile attributes can be set, for UdsResponse, defined attributes
refer to the positivity of the response, and its NRC if negative.
class UdsResponse(UserList):
NEGATIVE_RESPONSE_SID = 0x7F
def __init__(self, response_data) -> None:
super().__init__(response_data)
self.is_negative = False
self.nrc = None
if self.data and self.data[0] == self.NEGATIVE_RESPONSE_SID:
self.is_negative = True
self.nrc = NegativeResponseCode(self.data[2])
Here is an example:
import pykiso
from pykiso.auxiliaries import uds_aux
from collections import UserList
@pykiso.define_test_parameters(suite_id=1, case_id=1, aux_list=[uds_aux])
class ExampleUdsTest(pykiso.BasicTest):
def setUp(self):
"""Hook method from unittest in order to execute code before test case run.
"""
pass
def test_run(self):
# Set extended session
diag_session_response = uds_aux.send_uds_raw([0x10, 0x03])
self.assertEqual(diag_session_response[:2], [0x50, 0x03])
self.assertEqual(type(diag_session_response), UserList)
self.assertFalse(diag_session_response.is_negative)
def tearDown(self):
"""Hook method from unittest in order to execute code after test case run.
"""
pass
Send UDS Config Request
Send UDS request as a configurable data dictionary. This method can be more practical for UDS requests with long payloads and a multitude of parameters.
The method send_uds_config(pykiso.lib.auxiliaries.udsaux.uds_auxiliary.UdsAuxiliary.send_uds_config()
) takes one mandatory parameter msg_to_send and an optional one timeout_in_s.
The parameter msg_to_send is the UDS request defined as a configurable dictionary that always respects the below defined template:
Note
this feature is only available if a valid ODX file is given at auxiliary configuration level
req = {
'service': %SERVICE_ID%,
'data': %DATA%
}
SERVICE_ID -> SID (Service Identifier) of the UDS request either defined as a byte or the corresponding enum label:
class IsoServices(IntEnum):
DiagnosticSessionControl = 0x10
EcuReset = 0x11
SecurityAccess = 0x27
CommunicationControl = 0x28
TesterPresent = 0x3E
AccessTimingParameter = 0x83
SecuredDataTransmission = 0x84
ControlDTCSetting = 0x85
ResponseOnEvent = 0x86
LinkControl = 0x87
ReadDataByIdentifier = 0x22
ReadMemoryByAddress = 0x23
ReadScalingDataByIdentifier = 0x24
ReadDataByPeriodicIdentifier = 0x2A
DynamicallyDefineDataIdentifier = 0x2C
WriteDataByIdentifier = 0x2E
WriteMemoryByAddress = 0x3D
ClearDiagnosticInformation = 0x14
ReadDTCInformation = 0x19
InputOutputControlByIdentifier = 0x2F
RoutineControl = 0x31
RequestDownload = 0x34
RequestUpload = 0x35
TransferData = 0x36
RequestTransferExit = 0x37
- DATA -> dictionary that contains the following keys:
‘parameter’: DID (Data Identifier) of the UDS request. (In most UDS services with DID)
%param_n%: one or many keys that represent the parameters related to the service, those depend on ODX definition that is tested.
See some examples of UDS requests below:
import pykiso
from pykiso.auxiliaries import uds_aux
from uds import IsoServices
@pykiso.define_test_parameters(suite_id=1, case_id=1, aux_list=[uds_aux])
class ExampleUdsTest(pykiso.BasicTest):
def setUp(self):
"""Hook method from unittest in order to execute code before test case run.
"""
pass
def test_run(self):
extendedSession_req = {
"service": IsoServices.DiagnosticSessionControl,
"data": {"parameter": "Extended Diagnostic Session"},
}
diag_session_response = uds_aux.send_uds_config(extendedSession_req)
def tearDown(self):
"""Hook method from unittest in order to execute code after test case run.
"""
pass
The optional parameter timeout_in_s (by default fixed to 6 seconds) simply represents the maximum amount of time in second to wait for a response from the device under test. If this timeout is reached, the uds-auxiliary stops to acquire and log an error.
If the corresponding response is received from entity under test, send_uds_config method returns it also as a preconfigured dictionary. In case of a UDS positive response and no data to be returned, None is returned by the send_uds_config method. In case of a UDS negative response, a dictionary with the key ‘NRC’ is returned and the NRC value. Optionally, ‘NRC_Label’ may be returned if it is defined in ODX for the called service, containing the uds negative response description.
UDS Reset functions
Reset might be integrated in different tests.
The methods:
soft_rest(
pykiso.lib.auxiliaries.udsaux.uds_auxiliary.UdsAuxiliary.soft_reset()
)hard_reset(
pykiso.lib.auxiliaries.udsaux.uds_auxiliary.UdsAuxiliary.hard_reset()
)force_ecu_reset(
udsaux.uds_auxiliary.UdsAuxiliary.force_ecu_reset()
)
do not take any argument, and regarding the config (with our without odx file) will send either raw message, or uds config (except for the key_off_on methods, but can remain acceptable for odx uds config)
Soft reset
uds_aux.soft_reset()
UDS check functions
Check functions might be integrated in different tests.
The methods:
check_raw_response_negative(
pykiso.lib.auxiliaries.udsaux.uds_auxiliary.UdsAuxiliary.check_raw_response_negative()
)check_raw_response_positive(
pykiso.lib.auxiliaries.udsaux.uds_auxiliary.UdsAuxiliary.check_raw_response_positive()
)
The methods take as only mandatory argument the received response. The parameter rest is the response as a userlist object.
#Check raw response is positive
uds_aux.check_raw_response_positive(resp)
#Check raw response is negative
uds_aux.check_raw_response_negative(resp)
UDS read & write data
Read data(udsaux.uds_auxiliary.UdsAuxiliary.read_data()
) and write(udsaux.uds_auxiliary.UdsAuxiliary.write_data()
)
are two helper API that use send_uds_config with specific ISO services (udsaux.uds_utils.UdsAuxiliary.read_data()
)
ReadDataByIdentifier = 0x22
WriteDataByIdentifier = 0x2E
Using write_data takes two arguments : parameter, and value. Parameter is simply a string that refer to the name of the data you want to modify, and value is simply the value you want to assign to the chosen parameters API must return None in case of positive response, and dictionary with NRC in it (for further information, check in send_uds_config documentation). Using this API is similar to do this :
req = {
'service': IsoServices.WriteDataByIdentifier,
'data': {'parameter': 'MyProduct', 'dataRecord': [('SuperProduct', '12345')]}
}
resp = uds_aux.send_uds_config(writeProductCode_req)
return resp
In the same way, read_data takes one argument : parameter.
Parameter is a string that contain the name of the data that is to be read. API must return dictionary with either data associated to the read parameter, or NRC.
UDS tester present sender
In order for any diagnostic session to be kept open, a tester presence frame has to be sent every 5 seconds. For this purpose, the tester present sender context manager can be used, it will send the tester present frame at the period given, allowing you to keep the session open for more than 5 seconds.
# start sending tester present messages every 3 seconds until the context manager is exited
with uds_aux.tester_present_sender(period=3):
# Perform uds commands here
It is also possible to start and stop the tester present sender manually with the methods start_tester_present_sender and stop_tester_present_sender.
# start sending tester present messages every 1 seconds until the context manager is exited
uds_aux.start_tester_present_sender(period=1)
# Perform uds commands here
uds_aux.stop_tester_present_sender()
It is then possible to check if the tester present is active with the attribute is_tester_present
if uds_aux.is_tester_present:
# Perform commands here