Skip to content

Commit 2c011f4

Browse files
committed
Report warning on unknown NRC (2020 support)
1 parent 4f5f02d commit 2c011f4

File tree

6 files changed

+119
-14
lines changed

6 files changed

+119
-14
lines changed

doc/source/udsoncan/questions_answers.rst

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,8 @@ What version of the standard has been used?
66

77
.. epigraph::
88

9-
The cod ewas originally written based on ISO-14229:2006. Some addition from the 2013 version has been added, but not exhaustively.
9+
The code was originally written based on ISO-14229:2006. Some addition from the 2013 and 2020 version has been added, but not exhaustively.
1010

11-
Can we expect an update for the 2020 version?
12-
---------------------------------------------
13-
14-
.. epigraph::
15-
16-
Yes, one day, when I'll put my hands on the 2020 document.
17-
Access to ISO standard costs money and this project is 100% voluntary.
18-
19-
-----
2011

2112
How reliable is this code?
2213
--------------------------
@@ -28,6 +19,8 @@ How reliable is this code?
2819

2920
Only a few common services have been tested on a real ECU.
3021

22+
The project lacks static type check, but it is in the plan to introduce it.
23+
3124
-----
3225

3326
Why is there unimplemented services?
@@ -39,6 +32,7 @@ Why is there unimplemented services?
3932

4033
- The actual synchronous client doesn't support it.
4134
- The ratio of "service usage in the industry" over "the amount of work necessary to implement it" is too poor.
35+
- The service has been added in the 2020 version and I haven't taken the time to implement it.
4236

4337
As for the client capabilities, I am aware that the single-request/single-response mechanism of the actual client is limiting. I believe it is enough to handle the majority of today's use-cases.
4438
I may work in a future version for a more sophisticated client that will have message queues for each service with callback and everything, therefore allowing asynchronous services such as :ref:`ResponseOnEvent<ResponseOnEvent>` or :ref:`ReadDataByPeriodicIdentifier<ReadDataByPeriodicIdentifier>`

doc/source/udsoncan/request_response.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ Response Codes
5252
:members:
5353
:undoc-members:
5454
:member-order: bysource
55-
:exclude-members: get_name, is_negative
55+
:exclude-members: get_name, is_negative, is_supported_by_standard

test/test_response.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from udsoncan import Response, services
22
from test.UdsTest import UdsTest
3+
import inspect
34

45
class DummyServiceNormal(services.BaseService):
56
_sid = 0x13
@@ -125,3 +126,20 @@ def test_from_input_param(self):
125126
with self.assertRaises(ValueError):
126127
response = Response(service=DummyServiceNormal(), code = 0x10, data=11)
127128

129+
def test_all_response_code_have_version(self):
130+
codes = [ member[1] for member in inspect.getmembers(Response.Code) if isinstance(member[1], int) and not member[0].startswith('_')]
131+
self.assertGreater(len(codes), 0)
132+
for code in codes:
133+
# Make sure no exception is raised
134+
Response.Code.is_supported_by_standard(code, 2006)
135+
Response.Code.is_supported_by_standard(code, 2013)
136+
Response.Code.is_supported_by_standard(code, 2020)
137+
138+
# Case of known code introduced in 2020
139+
self.assertFalse(Response.Code.is_supported_by_standard(Response.Code.ResourceTemporarilyNotAvailable , 2006))
140+
self.assertFalse(Response.Code.is_supported_by_standard(Response.Code.ResourceTemporarilyNotAvailable , 2013))
141+
self.assertTrue(Response.Code.is_supported_by_standard(Response.Code.ResourceTemporarilyNotAvailable , 2020))
142+
143+
self.assertTrue(Response.Code.is_supported_by_standard(Response.Code.GeneralReject , 2006))
144+
self.assertTrue(Response.Code.is_supported_by_standard(Response.Code.GeneralReject , 2013))
145+
self.assertTrue(Response.Code.is_supported_by_standard(Response.Code.GeneralReject , 2020))

udsoncan/Response.py

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ class Code:
113113
ThrottlePedalTooLow = 0x8B
114114
TransmissionRangeNotInNeutral = 0x8C
115115
TransmissionRangeNotInGear = 0x8D
116-
ISOSAEReserved = 0x8E
117116
BrakeSwitchNotClosed = 0x8F
118117
ShifterLeverNotInPark = 0x90
119118
TorqueConverterClutchLocked = 0x91
@@ -131,6 +130,92 @@ class Code:
131130
SecuredLinkNotSupported = 0x38 + 6
132131
CertificateNotAvailable = 0x38 + 7
133132
AuditTrailInformationNotAvailable = 0x38 + 8
133+
134+
@classmethod
135+
def is_supported_by_standard(cls, code, standard_version):
136+
if not isinstance(code, int):
137+
raise ValueError("given code must be an integer value, not %s" % (code.__class__.__name__))
138+
139+
if not isinstance(standard_version, int):
140+
raise ValueError("given standard_version must be an integer value, not %s" % (standard_version.__class__.__name__))
141+
142+
codes_version = {
143+
cls.PositiveResponse : 2006,
144+
cls.GeneralReject : 2006,
145+
cls.ServiceNotSupported : 2006,
146+
cls.SubFunctionNotSupported : 2006,
147+
cls.IncorrectMessageLengthOrInvalidFormat : 2006,
148+
cls.ResponseTooLong : 2006,
149+
cls.BusyRepeatRequest : 2006,
150+
cls.ConditionsNotCorrect : 2006,
151+
cls.RequestSequenceError : 2006,
152+
cls.NoResponseFromSubnetComponent : 2006,
153+
cls.FailurePreventsExecutionOfRequestedAction : 2006,
154+
cls.RequestOutOfRange : 2006,
155+
cls.SecurityAccessDenied : 2006,
156+
cls.AuthenticationRequired : 2006,
157+
cls.InvalidKey : 2006,
158+
cls.ExceedNumberOfAttempts : 2006,
159+
cls.RequiredTimeDelayNotExpired : 2006,
160+
cls.SecureDataTransmissionRequired : 2020,
161+
cls.SecureDataTransmissionNotAllowed : 2020,
162+
cls.SecureDataVerificationFailed : 2020,
163+
cls.CertificateVerificationFailed_InvalidTimePeriod : 2020,
164+
cls.CertificateVerificationFailed_InvalidSignature : 2020,
165+
cls.CertificateVerificationFailed_InvalidChainOfTrust : 2020,
166+
cls.CertificateVerificationFailed_InvalidType : 2020,
167+
cls.CertificateVerificationFailed_InvalidFormat : 2020,
168+
cls.CertificateVerificationFailed_InvalidContent : 2020,
169+
cls.CertificateVerificationFailed_InvalidScope : 2020,
170+
cls.CertificateVerificationFailed_InvalidCertificate : 2020,
171+
cls.OwnershipVerificationFailed : 2020,
172+
cls.ChallengeCalculationFailed : 2020,
173+
cls.SettingAccessRightsFailed : 2020,
174+
cls.SessionKeyCreationDerivationFailed : 2020,
175+
cls.ConfigurationDataUsageFailed : 2020,
176+
cls.DeAuthenticationFailed : 2020,
177+
cls.UploadDownloadNotAccepted : 2006,
178+
cls.TransferDataSuspended : 2006,
179+
cls.GeneralProgrammingFailure : 2006,
180+
cls.WrongBlockSequenceCounter : 2006,
181+
cls.RequestCorrectlyReceived_ResponsePending : 2006,
182+
cls.SubFunctionNotSupportedInActiveSession : 2006,
183+
cls.ServiceNotSupportedInActiveSession : 2006,
184+
cls.RpmTooHigh : 2006,
185+
cls.RpmTooLow : 2006,
186+
cls.EngineIsRunning : 2006,
187+
cls.EngineIsNotRunning : 2006,
188+
cls.EngineRunTimeTooLow : 2006,
189+
cls.TemperatureTooHigh : 2006,
190+
cls.TemperatureTooLow : 2006,
191+
cls.VehicleSpeedTooHigh : 2006,
192+
cls.VehicleSpeedTooLow : 2006,
193+
cls.ThrottlePedalTooHigh : 2006,
194+
cls.ThrottlePedalTooLow : 2006,
195+
cls.TransmissionRangeNotInNeutral : 2006,
196+
cls.TransmissionRangeNotInGear : 2006,
197+
cls.BrakeSwitchNotClosed : 2006,
198+
cls.ShifterLeverNotInPark : 2006,
199+
cls.TorqueConverterClutchLocked : 2006,
200+
cls.VoltageTooHigh : 2006,
201+
cls.VoltageTooLow : 2006,
202+
cls.ResourceTemporarilyNotAvailable : 2020,
203+
cls.GeneralSecurityViolation : 2006,
204+
cls.SecuredModeRequested : 2006,
205+
cls.InsufficientProtection : 2006,
206+
cls.TerminationWithSignatureRequested : 2006,
207+
cls.AccessDenied : 2006,
208+
cls.VersionNotSupported : 2006,
209+
cls.SecuredLinkNotSupported : 2006,
210+
cls.CertificateNotAvailable : 2006,
211+
cls.AuditTrailInformationNotAvailable : 2006,
212+
}
213+
214+
if code not in codes_version:
215+
raise ValueError('Do not know the standard version in which this code has been introduced: %s' % (code))
216+
217+
return standard_version >= codes_version[code]
218+
134219

135220
#Returns the name of the response code as a string
136221
@classmethod
@@ -154,7 +239,8 @@ def is_negative(cls, given_id):
154239
if isinstance(member[1], int):
155240
if member[1] == given_id:
156241
return True
157-
return False
242+
return False
243+
158244

159245

160246
def __init__(self, service = None, code = None, data=None):

udsoncan/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,12 @@ def send_request(self, request, timeout=-1):
19911991
raise UnexpectedResponseException(response, msg)
19921992

19931993
if not response.positive:
1994+
try:
1995+
if not Response.Code.is_supported_by_standard(response.code, self.config['standard_version']):
1996+
self.logger.warning('Given response code "%s" (0x%02x) is not supported byt the UDS standard version that the clients s enforcing (%s)' % (response.code_name, response.code, self.config['standard_version']))
1997+
except ValueError:
1998+
self.logger.warning('Unkown response code "%s" (0x%02x)', response.code_name, response.code)
1999+
19942000
if not request.service.is_supported_negative_response(response.code):
19952001
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))
19962002

udsoncan/services/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ class BaseService(ABC):
3838
Response.Code.FailurePreventsExecutionOfRequestedAction,
3939
Response.Code.SecurityAccessDenied, # ISO-14229:2006 Table A.1: "Besides the mandatory use of this negative response code as specified in the applicable services within ISO 14229, this negative response code can also be used for any case where security is required and is not yet granted to perform the required service."
4040
Response.Code.RequestCorrectlyReceived_ResponsePending,
41-
Response.Code.ServiceNotSupportedInActiveSession
41+
Response.Code.ServiceNotSupportedInActiveSession,
42+
Response.Code.ResourceTemporarilyNotAvailable
4243
]
4344

4445
@classmethod # Returns the service ID used for a client request

0 commit comments

Comments
 (0)