Skip to content

Commit ca5d8cc

Browse files
committed
Merge branch 'wanam-master'
2 parents 6049a19 + 9373947 commit ca5d8cc

File tree

3 files changed

+80
-6
lines changed

3 files changed

+80
-6
lines changed

test/client/test_read_data_by_identifier.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ def decode(self, did_payload):
1717
def __len__(self):
1818
return 1
1919

20+
class ReadRemainingDataCodec(DidCodec):
21+
22+
def encode(self, *args, **kwargs):
23+
return b''
24+
25+
def decode(self, did_payload):
26+
return did_payload
27+
28+
def __len__(self):
29+
raise self.ReadAllRemainingData
30+
31+
class CodecWithNoLength(DidCodec):
32+
33+
def encode(self, *args, **kwargs):
34+
return b''
35+
36+
def decode(self, did_payload):
37+
return did_payload
38+
39+
2040
class TestReadDataByIdentifier(ClientServerTest):
2141
def __init__(self, *args, **kwargs):
2242
ClientServerTest.__init__(self, *args, **kwargs)
@@ -26,7 +46,9 @@ def postClientSetUp(self):
2646
1 : '>H',
2747
2 : '<H',
2848
3 : StubbedDidCodec,
29-
4 : AsciiCodec(5)
49+
4 : AsciiCodec(5),
50+
5 : ReadRemainingDataCodec,
51+
6 : CodecWithNoLength
3052
}
3153

3254
def test_rdbi_single_success(self):
@@ -125,10 +147,29 @@ def _test_rdbi_multiple_zero_padding_not_tolerated_no_exception(self):
125147
self.udsclient.config['data_identifiers'][0] = 'B'*i
126148
response = self.udsclient.read_data_by_identifier(didlist = [1,2,3])
127149
self.assertTrue(response.valid)
128-
self.assertTrue(response.unexpected)
150+
self.assertTrue(response.unexpected)
129151

152+
def test_rdbi_variable_size_did(self):
153+
self.wait_request_and_respond(b"\x62\x00\x01\x12\x34\x00\x02\x56\x78\x00\x05\xaa\xbb\xcc\xdd")
154+
155+
def _test_rdbi_variable_size_did(self):
156+
response = self.udsclient.read_data_by_identifier(didlist = [1,2,5])
157+
self.assertTrue(response.positive)
158+
values = response.service_data.values
159+
self.assertEqual(values[1], (0x1234,))
160+
self.assertEqual(values[2], (0x7856,))
161+
self.assertEqual(values[5], b'\xaa\xbb\xcc\xdd')
162+
163+
# DID 5 read all the data up to the end. Makes no sense to read another DID after that.
164+
def test_rdbi_variable_size_did_not_last(self):
165+
pass
166+
167+
def _test_rdbi_variable_size_did_not_last(self):
168+
with self.assertRaises(ValueError):
169+
self.udsclient.read_data_by_identifier(didlist = [1,2,5,3])
170+
130171
def test_rdbi_incomplete_response_exception(self):
131-
self.wait_request_and_respond(b"\x62\x00\x01\x12\x34\x00\x02\x56\x78\x00\x03")
172+
self.wait_request_and_respond(b"\x62\x00\x01\x12\x34\x00\x02\x56\x78\x00\x03")
132173

133174
def _test_rdbi_incomplete_response_exception(self):
134175
with self.assertRaises(InvalidResponseException):
@@ -211,3 +252,10 @@ def test_no_config(self):
211252
def _test_no_config(self):
212253
with self.assertRaises(ConfigError):
213254
self.udsclient.read_data_by_identifier(didlist=[1,2,3,99])
255+
256+
def test_no_length(self):
257+
pass
258+
259+
def _test_no_length(self):
260+
with self.assertRaises(NotImplementedError):
261+
self.udsclient.read_data_by_identifier(didlist=[6])

udsoncan/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class DidCodec:
4040
:type packstr: string
4141
"""
4242

43+
class ReadAllRemainingData(Exception):
44+
pass
45+
4346
def __init__(self, packstr=None):
4447
self.packstr = packstr
4548

udsoncan/services/ReadDataByIdentifier.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,28 @@ def make_request(cls, didlist, didconfig):
4545
:raises ConfigError: If didlist contains a DID not defined in didconfig
4646
"""
4747
from udsoncan import Request
48+
from udsoncan import DidCodec
49+
4850
didlist = cls.validate_didlist_input(didlist)
4951

5052
req = Request(cls)
5153
ServiceHelper.check_did_config(didlist, didconfig)
54+
55+
did_reading_all_data = None
56+
for did in didlist:
57+
if did not in didconfig: # Already checked in check_did_config. Paranoid check
58+
raise ConfigError(key=did, msg='Actual data identifier configuration contains no definition for data identifier 0x%04x' % did)
59+
60+
codec = DidCodec.from_config(didconfig[did])
61+
try:
62+
length = len(codec)
63+
if did_reading_all_data is not None:
64+
raise ValueError('Did 0x%04X is configured to read the rest of the payload (__len__ raisong ReadAllRemainingData), but a subsequent DID is requested (0x%04x)' % (did_reading_all_data, did))
65+
except DidCodec.ReadAllRemainingData:
66+
if did_reading_all_data is not None:
67+
raise ValueError('It is impossible to read 2 DIDs configured to read the rest of the payload (__len__ raising ReadAllRemainingData). Dids are : 0x%04X and 0x%04X' % (did_reading_all_data, did))
68+
did_reading_all_data = did
69+
5270
req.data = struct.pack('>'+'H'*len(didlist), *didlist) #Encode list of DID
5371

5472
return req
@@ -104,11 +122,16 @@ def interpret_response(cls, response, didlist, didconfig, tolerate_zero_padding=
104122
codec = DidCodec.from_config(didconfig[did])
105123
offset+=2
106124

107-
if len(response.data) < offset+len(codec):
125+
try:
126+
payload_size = len(codec)
127+
except DidCodec.ReadAllRemainingData:
128+
payload_size = len(response.data) - offset
129+
130+
if len(response.data) < offset+payload_size:
108131
raise InvalidResponseException(response, "Value for data identifier 0x%04x was incomplete according to definition in configuration" % did)
109132

110-
subpayload = response.data[offset:offset+len(codec)]
111-
offset += len(codec) # Codec must define a __len__ function that matches the encoded payload length.
133+
subpayload = response.data[offset:offset+payload_size]
134+
offset += payload_size # Codec must define a __len__ function that matches the encoded payload length.
112135
val = codec.decode(subpayload)
113136
response.service_data.values[did] = val
114137

0 commit comments

Comments
 (0)