From e664c637ad461b1f9f75c167ee25a65f6ca63972 Mon Sep 17 00:00:00 2001 From: Carl Ljungholm Date: Fri, 1 Sep 2023 13:27:57 +0200 Subject: [PATCH] Use smaller of response size and size in OD Some devices use simplified logic for sending SDO response. They send an expedited 4 byte response for all sizes up to U32/I32. Unpacking code expects data size to exactly match the size in the object dictionary. Therefore use the smaller of the size for the variable in the OD and the actual response size. --- canopen/sdo/client.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/canopen/sdo/client.py b/canopen/sdo/client.py index 21517717..370aab72 100644 --- a/canopen/sdo/client.py +++ b/canopen/sdo/client.py @@ -114,21 +114,22 @@ def upload(self, index: int, subindex: int) -> bytes: When node responds with an error. """ with self.open(index, subindex, buffering=0) as fp: - size = fp.size + response_size = fp.size data = fp.read() - if size is None: - # Node did not specify how many bytes to use - # Try to find out using Object Dictionary - var = self.od.get_variable(index, subindex) - if var is not None: - # Found a matching variable in OD - # If this is a data type (string, domain etc) the size is - # unknown anyway so keep the data as is - if var.data_type not in objectdictionary.DATA_TYPES: - # Get the size in bytes for this variable - size = len(var) // 8 + + # If size is available through variable in OD, then use the smaller of the two sizes. + # Some devices send U32/I32 even if variable is smaller in OD + var = self.od.get_variable(index, subindex) + if var is not None: + # Found a matching variable in OD + # If this is a data type (string, domain etc) the size is + # unknown anyway so keep the data as is + if var.data_type not in objectdictionary.DATA_TYPES: + # Get the size in bytes for this variable + var_size = len(var) // 8 + if response_size is None or var_size < response_size: # Truncate the data to specified size - data = data[0:size] + data = data[0:var_size] return data def download(