Skip to content

Commit 49e4a73

Browse files
committed
Move data truncation from SDO upload to data decode
1 parent 7ddb19b commit 49e4a73

File tree

3 files changed

+14
-20
lines changed

3 files changed

+14
-20
lines changed

canopen/objectdictionary/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,16 @@ def decode_raw(self, data: bytes) -> Union[int, float, str, bytes, bytearray]:
429429
# Strip any trailing NUL characters from C-based systems
430430
return data.decode("utf_16_le", errors="ignore").rstrip("\x00")
431431
elif self.data_type in self.STRUCT_TYPES:
432+
size = self.STRUCT_TYPES[self.data_type].size
433+
logger.warning(f"Decoding data {data!r} of type 0x%X at %s",
434+
self.data_type, pretty_index(self.index, self.subindex))
435+
logger.warning(f"Size: {size} bytes, data length: {len(data)} bytes")
436+
if len(data) > size:
437+
logger.warning("Excessive data in %s. Data type 0x%X expects %s bytes, got %s",
438+
pretty_index(self.index, self.subindex), self.data_type,
439+
size, len(data))
440+
# Truncate the data to the expected size
441+
data = data[:size]
432442
try:
433443
value, = self.STRUCT_TYPES[self.data_type].unpack(data)
434444
return value

canopen/sdo/client.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -118,23 +118,7 @@ def upload(self, index: int, subindex: int) -> bytes:
118118
When node responds with an error.
119119
"""
120120
with self.open(index, subindex, buffering=0) as fp:
121-
response_size = fp.size
122-
data = fp.read()
123-
124-
# If size is available through variable in OD, then use the smaller of the two sizes.
125-
# Some devices send U32/I32 even if variable is smaller in OD
126-
var = self.od.get_variable(index, subindex)
127-
if var is not None:
128-
# Found a matching variable in OD
129-
# If this is a data type (string, domain etc) the size is
130-
# unknown anyway so keep the data as is
131-
if var.data_type not in objectdictionary.DATA_TYPES:
132-
# Get the size in bytes for this variable
133-
var_size = len(var) // 8
134-
if response_size is None or var_size < response_size:
135-
# Truncate the data to specified size
136-
data = data[0:var_size]
137-
return data
121+
return fp.read()
138122

139123
def download(
140124
self,

test/test_sdo.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ def test_size_not_specified(self):
104104
]
105105
# Make sure the size of the data is 1 byte
106106
data = self.network[2].sdo.upload(0x1400, 2)
107-
self.assertEqual(data, b'\xfe')
107+
self.assertEqual(data, b'\xfe\x00\x00\x00')
108+
data = self.network[2].object_dictionary[0x1400][2].decode_raw(data)
109+
self.assertEqual(data, 254)
108110
self.assertTrue(self.message_sent)
109111

110112
def test_expedited_download(self):
@@ -814,7 +816,6 @@ def test_unknown_od_112(self):
814816

815817
def test_unknown_datatype32(self):
816818
"""Test an unknown datatype, but known OD, of 32 bits (4 bytes)."""
817-
return # FIXME: Disabled temporarily until datatype conditionals are fixed, see #436
818819
# Add fake entry 0x2100 to OD, using fake datatype 0xFF
819820
if 0x2100 not in self.node.object_dictionary:
820821
fake_var = ODVariable("Fake", 0x2100)
@@ -829,7 +830,6 @@ def test_unknown_datatype32(self):
829830

830831
def test_unknown_datatype112(self):
831832
"""Test an unknown datatype, but known OD, of 112 bits (14 bytes)."""
832-
return # FIXME: Disabled temporarily until datatype conditionals are fixed, see #436
833833
# Add fake entry 0x2100 to OD, using fake datatype 0xFF
834834
if 0x2100 not in self.node.object_dictionary:
835835
fake_var = ODVariable("Fake", 0x2100)

0 commit comments

Comments
 (0)