Skip to content

Commit f0f7d00

Browse files
authored
Add node id number to comm control (#217)
Added support for nodeIdentificationNumber in communicationControl service (2013,2020) Fixes #216
1 parent bf0cf11 commit f0f7d00

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed

test/client/test_communication_control.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from udsoncan.exceptions import *
33

44
from test.ClientServerTest import ClientServerTest
5+
from udsoncan import latest_standard
56

67

78
class TestCommunicationControl(ClientServerTest):
@@ -29,6 +30,18 @@ def _test_comcontrol_enable_node(self):
2930
self.assertTrue(response.positive)
3031
self.assertEqual(response.service_data.control_type_echo, control_type)
3132

33+
def test_comcontrol_enable_node_with_enhanced_addr_info(self):
34+
request = self.conn.touserqueue.get(timeout=0.2)
35+
self.assertEqual(request, b"\x28\x05\x01\x12\x34")
36+
self.conn.fromuserqueue.put(b"\x68\x05") # Positive response
37+
38+
def _test_comcontrol_enable_node_with_enhanced_addr_info(self):
39+
control_type = services.CommunicationControl.ControlType.enableRxAndTxWithEnhancedAddressInformation
40+
com_type = CommunicationType(subnet=CommunicationType.Subnet.node, normal_msg=True)
41+
response = self.udsclient.communication_control(control_type=control_type, communication_type=com_type, node_id=0x1234)
42+
self.assertTrue(response.positive)
43+
self.assertEqual(response.service_data.control_type_echo, control_type)
44+
3245
def test_comcontrol_enable_node_spr(self):
3346
request = self.conn.touserqueue.get(timeout=0.2)
3447
self.assertEqual(request, b"\x28\x80\x01")
@@ -148,3 +161,21 @@ def _test_bad_param(self):
148161

149162
with self.assertRaises(ValueError):
150163
self.udsclient.communication_control(control_type=0, communication_type='x')
164+
165+
with self.assertRaises(ValueError):
166+
self.udsclient.communication_control(
167+
control_type=services.CommunicationControl.ControlType.enableRxAndDisableTxWithEnhancedAddressInformation,
168+
communication_type=CommunicationType(subnet=CommunicationType.Subnet.node, normal_msg=True)) # Missing node_id
169+
170+
with self.assertRaises(ValueError):
171+
self.udsclient.communication_control(
172+
control_type=services.CommunicationControl.ControlType.enableRxAndTxWithEnhancedAddressInformation,
173+
communication_type=CommunicationType(subnet=CommunicationType.Subnet.node, normal_msg=True)) # Missing node_id
174+
175+
with self.assertRaises(ValueError):
176+
self.udsclient.config['standard_version'] = 2006
177+
self.udsclient.communication_control(
178+
control_type=services.CommunicationControl.ControlType.enableRxAndTxWithEnhancedAddressInformation,
179+
communication_type=CommunicationType(subnet=CommunicationType.Subnet.node, normal_msg=True),
180+
node_id=0x1234) # node_id not allowed
181+
self.udsclient.config['standard_version'] = latest_standard

udsoncan/client.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,8 @@ def access_timing_parameter(self,
813813
@standard_error_management
814814
def communication_control(self,
815815
control_type: int,
816-
communication_type: Union[int, bytes, CommunicationType]
816+
communication_type: Union[int, bytes, CommunicationType],
817+
node_id: Optional[int] = None,
817818
) -> Optional[services.CommunicationControl.InterpretedResponse]:
818819
"""
819820
Switches the transmission or reception of certain messages on/off with :ref:`CommunicationControl<CommunicationControl>` service.
@@ -826,15 +827,29 @@ def communication_control(self,
826827
:param communication_type: Indicates what section of the network and the type of message that should be affected by the command. Refer to :ref:`CommunicationType<CommunicationType>` for more details. If an `integer` or a `bytes` is given, the value will be decoded to create the required :ref:`CommunicationType<CommunicationType>` object
827828
:type communication_type: :ref:`CommunicationType<CommunicationType>`, bytes, int
828829
830+
:param node_id: DTC memory identifier (nodeIdentificationNumber). This value is user defined and introduced in 2013 version of ISO-14229-1.
831+
Possible only when control type is ``enableRxAndDisableTxWithEnhancedAddressInformation`` or ``enableRxAndTxWithEnhancedAddressInformation``
832+
Only added to the request payload when different from None. Default : None
833+
:type node_id: int
834+
829835
:return: The server response parsed by :meth:`CommunicationControl.interpret_response<udsoncan.services.CommunicationControl.interpret_response>`
830836
:rtype: :ref:`Response<Response>`
831837
"""
832838

833839
communication_type = services.CommunicationControl.normalize_communication_type(communication_type)
834840

835-
request = services.CommunicationControl.make_request(control_type, communication_type)
836-
self.logger.info('%s - ControlType=0x%02x (%s) - Sending request with a CommunicationType byte of 0x%02x (%s)' % (self.service_log_prefix(services.CommunicationControl),
837-
control_type, services.CommunicationControl.ControlType.get_name(control_type), communication_type.get_byte_as_int(), str(communication_type)))
841+
request = services.CommunicationControl.make_request(
842+
control_type, communication_type, node_id, standard_version=self.config['standard_version'])
843+
844+
self.logger.info('%s - ControlType=0x%02x (%s) - Sending request with a CommunicationType byte of 0x%02x (%s). nodeIdentificationNumber=%s ' % (
845+
self.service_log_prefix(services.CommunicationControl),
846+
control_type,
847+
services.CommunicationControl.ControlType.get_name(control_type),
848+
communication_type.get_byte_as_int(),
849+
str(communication_type),
850+
str(node_id)
851+
)
852+
)
838853

839854
response = self.send_request(request)
840855
if response is None:

udsoncan/services/ClearDiagnosticInformation.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ def make_request(cls, group: int = 0xFFFFFF, memory_selection: Optional[int] = N
3838
:param group: DTC mask ranging from 0 to 0xFFFFFF. 0xFFFFFF means all DTCs
3939
:type group: int
4040
41+
:param memory_selection: Number identifying the respective DTC memory. This value is user defined and introduced in 2013 version of ISO-14229-1.
42+
Only added to the request payload when different from None. Default : None
43+
:type memory_selection: int
44+
45+
:param standard_version: The version of the ISO-14229 (the year). eg. 2006, 2013, 2020
46+
:type standard_version: int
47+
4148
:raises ValueError: If parameters are out of range, missing or wrong type
4249
"""
4350
tools.validate_int(group, min=0, max=0xFFFFFF, name='Group of DTC')

udsoncan/services/CommunicationControl.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
from udsoncan.BaseService import BaseService, BaseSubfunction, BaseResponseData
66
from udsoncan.ResponseCode import ResponseCode
77
import udsoncan.tools as tools
8+
from udsoncan import latest_standard
9+
import struct
810

9-
from typing import cast, Union
11+
from typing import cast, Union, Optional
1012

1113

1214
class CommunicationControl(BaseService):
@@ -22,6 +24,8 @@ class ControlType(BaseSubfunction):
2224
enableRxAndDisableTx = 1
2325
disableRxAndEnableTx = 2
2426
disableRxAndTx = 3
27+
enableRxAndDisableTxWithEnhancedAddressInformation = 4
28+
enableRxAndTxWithEnhancedAddressInformation = 5
2529

2630
supported_negative_response = [ResponseCode.SubFunctionNotSupported,
2731
ResponseCode.IncorrectMessageLengthOrInvalidFormat,
@@ -55,7 +59,7 @@ def normalize_communication_type(self, communication_type: Union[int, bytes, Com
5559
return communication_type
5660

5761
@classmethod
58-
def make_request(cls, control_type: int, communication_type: CommunicationType) -> Request:
62+
def make_request(cls, control_type: int, communication_type: CommunicationType, node_id: Optional[int] = None, standard_version=latest_standard) -> Request:
5963
"""
6064
Generates a request for CommunicationControl
6165
@@ -65,14 +69,39 @@ def make_request(cls, control_type: int, communication_type: CommunicationType)
6569
:param communication_type: The communication type requested.
6670
:type communication_type: :ref:`CommunicationType <CommunicationType>`, int, bytes
6771
72+
:param node_id: DTC memory identifier. This value is user defined and introduced in 2013 version of ISO-14229-1.
73+
Possible and required only when ``control_type`` is ``enableRxAndDisableTxWithEnhancedAddressInformation`` or ``enableRxAndTxWithEnhancedAddressInformation``
74+
Default : ``None``
75+
:type node_id: int
76+
77+
:param standard_version: The version of the ISO-14229 (the year). eg. 2006, 2013, 2020
78+
:type standard_version: int
79+
6880
:raises ValueError: If parameters are out of range, missing or wrong type
6981
"""
7082
tools.validate_int(control_type, min=0, max=0x7F, name='Control type')
7183

84+
require_node_id = standard_version >= 2013 and control_type in (
85+
CommunicationControl.ControlType.enableRxAndDisableTxWithEnhancedAddressInformation,
86+
CommunicationControl.ControlType.enableRxAndTxWithEnhancedAddressInformation
87+
)
88+
89+
if require_node_id and node_id is None:
90+
raise ValueError(
91+
"node_id is required when the standard version is 2013 (or more recent) and when control_type is enableRxAndDisableTxWithEnhancedAddressInformation or enableRxAndTxWithEnhancedAddressInformation ")
92+
elif not require_node_id and node_id is not None:
93+
raise ValueError(
94+
"node_id is only possible when the standard version is 2013 (or more recent) and when control_type is enableRxAndDisableTxWithEnhancedAddressInformation or enableRxAndTxWithEnhancedAddressInformation ")
95+
7296
communication_type = cls.normalize_communication_type(communication_type)
7397
request = Request(service=cls, subfunction=control_type)
74-
request.data = communication_type.get_byte()
98+
payload = communication_type.get_byte()
99+
100+
if node_id is not None:
101+
tools.validate_int(node_id, min=0, max=0xFFFF, name='nodeIdentificationNumber')
102+
payload += struct.pack('>H', node_id)
75103

104+
request.data = payload
76105
return request
77106

78107
@classmethod

udsoncan/services/DiagnosticSessionControl.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ def interpret_response(cls, response: Response, standard_version: int = latest_s
8484
:param response: The received response to interpret
8585
:type response: :ref:`Response<Response>`
8686
87+
:param standard_version: The version of the ISO-14229 (the year). eg. 2006, 2013, 2020
88+
:type standard_version: int
89+
8790
:raises InvalidResponseException: If length of ``response.data`` is too short
8891
"""
8992
if response.data is None:

0 commit comments

Comments
 (0)