Skip to content

Commit c914bd7

Browse files
authored
Merge pull request #19 from cpavot/cpavot_uds_p2_server_max
Support P2 server max and P2* server max
2 parents 1bab07e + 50e2a07 commit c914bd7

File tree

1 file changed

+45
-16
lines changed

1 file changed

+45
-16
lines changed

udsoncan/client.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,17 @@ class Client:
2222
:param config: The :ref:`client configuration<client_config>`
2323
:type config: dict
2424
25-
:param request_timeout: Maximum amount of time to wait for a response after sending a request (in seconds). After this time is elapsed, a TimeoutException will be raised.
25+
:param request_timeout: Maximum amount of time in seconds to wait for the final response (positive or negative except NRC 0x78) after sending a request.
26+
After this time is elapsed, a TimeoutException will be raised. If less than or equal to p2_star, NRC 0x78 (requestCorrectlyReceived-ResponsePending) responses are not supported.
2627
:type request_timeout: int
28+
29+
:param p2_timeout: Maximum amount of time in seconds to wait for a response (positive, negative, or NRC 0x78). After this time is elapsed, a TimeoutException will be raised.
30+
See ISO 14229-2 (UDS Session Layer Services).
31+
:type p2_timeout: int
32+
33+
:param p2_star_timeout: Maximum amount of time in seconds to wait for a response (positive, negative, or NRC0x78) after the reception of a negative response with code 0x78
34+
(requestCorrectlyReceived-ResponsePending). After this time is elapsed, a TimeoutException will be raised. See ISO 14229-2 (UDS Session Layer Services).
35+
:type p2_star_timeout: int
2736
"""
2837

2938
class SuppressPositiveResponse:
@@ -37,9 +46,11 @@ def __enter__(self):
3746
def __exit__(self, type, value, traceback):
3847
self.enabled = False
3948

40-
def __init__(self, conn, config=default_client_config, request_timeout = 1):
49+
def __init__(self, conn, config=default_client_config, request_timeout=5, p2_timeout=1, p2_star_timeout=5):
4150
self.conn = conn
4251
self.request_timeout = request_timeout
52+
self.p2_timeout = p2_timeout
53+
self.p2_star_timeout = p2_star_timeout
4354
self.config = dict(config) # Makes a copy of given configuration
4455
self.suppress_positive_response = Client.SuppressPositiveResponse()
4556
self.last_response = None
@@ -1409,9 +1420,20 @@ def read_dtc_information(self, subfunction, status_mask=None, severity_mask=None
14091420

14101421
# Basic transmission of requests. This will need to be improved
14111422
def send_request(self, request, timeout=-1):
1412-
if timeout is not None and timeout < 0:
1413-
timeout = self.request_timeout
1414-
original_timeout = timeout
1423+
if timeout < 0:
1424+
# Timeout not provided by user: defaults to Client request_timeout value
1425+
overall_timeout = self.request_timeout
1426+
else:
1427+
overall_timeout = timeout
1428+
1429+
if overall_timeout > self.p2_star_timeout:
1430+
current_timeout = self.p2_timeout
1431+
response_pending_supported = True
1432+
else:
1433+
# NRC 0x78 (RequestCorrectlyReceived_ResponsePending) not supported
1434+
current_timeout = overall_timeout
1435+
response_pending_supported = False
1436+
14151437
self.conn.empty_rxqueue()
14161438
self.logger.debug("Sending request to server")
14171439
override_suppress_positive_response = False
@@ -1430,21 +1452,23 @@ def send_request(self, request, timeout=-1):
14301452
return
14311453

14321454
done_receiving = False
1455+
1456+
if response_pending_supported:
1457+
overall_timeout_time = time.time() + overall_timeout
1458+
else:
1459+
overall_timeout_time = None
1460+
14331461
while not done_receiving:
14341462
done_receiving = True
14351463
self.logger.debug("Waiting for server response")
14361464
try:
1437-
rx_time = time.time()
1438-
payload = self.conn.wait_frame(timeout=timeout, exception=True)
1439-
rx_time = time.time()-rx_time
1440-
if timeout is not None:
1441-
timeout =timeout - rx_time
1442-
if timeout < 0:
1443-
raise TimeoutException('Did not receive response in time (timeout=%.3f sec)' % original_timeout)
1444-
except TimeoutException as e:
1445-
raise TimeoutException('Did not receive response in time (timeout=%.3f sec)' % original_timeout)
1465+
payload = self.conn.wait_frame(timeout=current_timeout, exception=True)
1466+
except TimeoutException:
1467+
raise TimeoutException('Did not receive response in time (timeout=%.3f sec)' % current_timeout)
14461468
except Exception as e:
14471469
raise e
1470+
if overall_timeout_time is not None and overall_timeout_time - time.time() < 0:
1471+
raise TimeoutException('Did not receive final response in time (request timeout=%.3f sec)' % overall_timeout)
14481472

14491473
response = Response.from_payload(payload)
14501474
self.last_response = response
@@ -1462,8 +1486,13 @@ def send_request(self, request, timeout=-1):
14621486
self.logger.warning('Given response code "%s" (0x%02x) is not a supported negative response code according to UDS standard.' % (response.code_name, response.code))
14631487

14641488
if response.code == Response.Code.RequestCorrectlyReceived_ResponsePending:
1465-
done_receiving = False
1466-
self.logger.debug("Server requested to wait with response code %s (0x%02x)" % (response.code_name, response.code))
1489+
if response_pending_supported:
1490+
# Received a 0x78 NRC: timeout is now set to P2*
1491+
current_timeout = self.p2_star_timeout
1492+
done_receiving = False
1493+
self.logger.debug("Server requested to wait with response code %s (0x%02x), timeout is now set to %.3f seconds" % (response.code_name, response.code, current_timeout))
1494+
else:
1495+
raise NegativeResponseException(response, "RequestCorrectlyReceived_ResponsePending not supported")
14671496
else:
14681497
raise NegativeResponseException(response)
14691498

0 commit comments

Comments
 (0)