Skip to content

Commit b2fa0bb

Browse files
committed
Bugfix for #445
- changed save() Method of PdoBase to be more robust nad without an always true condition - use getattr directly in curtis hack - removed unused variables - added Test for PDO saving
1 parent 94f337d commit b2fa0bb

File tree

2 files changed

+44
-39
lines changed

2 files changed

+44
-39
lines changed

canopen/pdo/base.py

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ def __getitem_by_name(self, value):
215215
value, ', '.join(valid_values)))
216216

217217
def __getitem__(self, key: Union[int, str]) -> "PdoVariable":
218-
var = None
219218
if isinstance(key, int):
220219
# there is a maximum available of 8 slots per PDO map
221220
if key in range(0, 8):
@@ -360,7 +359,7 @@ def _raw_from(param):
360359
subindex = (value >> 8) & 0xFF
361360
# Ignore the highest bit, it is never valid for <= 64 PDO length
362361
size = value & 0x7F
363-
if hasattr(self.pdo_node.node, "curtis_hack") and self.pdo_node.node.curtis_hack: # Curtis HACK: mixed up field order
362+
if getattr(self.pdo_node.node, "curtis_hack", False): # Curtis HACK: mixed up field order
364363
index = value & 0xFFFF
365364
subindex = (value >> 16) & 0xFF
366365
size = (value >> 24) & 0x7F
@@ -371,8 +370,10 @@ def _raw_from(param):
371370

372371
def save(self) -> None:
373372
"""Save PDO configuration for this map using SDO."""
374-
logger.info("Setting COB-ID 0x%X and temporarily disabling PDO",
375-
self.cob_id)
373+
if self.cob_id is None:
374+
logger.debug("Skipping %s: no cob-id set", self.com_record.od.name)
375+
return
376+
logger.info("Setting COB-ID 0x%X and temporarily disabling PDO", self.cob_id)
376377
self.com_record[1].raw = self.cob_id | PDO_NOT_VALID | (RTR_NOT_ALLOWED if not self.rtr_allowed else 0x0)
377378
if self.trans_type is not None:
378379
logger.info("Setting transmission type to %d", self.trans_type)
@@ -387,39 +388,38 @@ def save(self) -> None:
387388
logger.info("Setting SYNC start value to %d", self.sync_start_value)
388389
self.com_record[6].raw = self.sync_start_value
389390

390-
if self.map is not None:
391-
try:
392-
self.map_array[0].raw = 0
393-
except SdoAbortedError:
394-
# WORKAROUND for broken implementations: If the array has a
395-
# fixed number of entries (count not writable), generate dummy
396-
# mappings for an invalid object 0x0000:00 to overwrite any
397-
# excess entries with all-zeros.
398-
self._fill_map(self.map_array[0].raw)
399-
subindex = 1
400-
for var in self.map:
401-
logger.info("Writing %s (0x%X:%d, %d bits) to PDO map",
402-
var.name, var.index, var.subindex, var.length)
403-
if hasattr(self.pdo_node.node, "curtis_hack") and self.pdo_node.node.curtis_hack: # Curtis HACK: mixed up field order
404-
self.map_array[subindex].raw = (var.index |
405-
var.subindex << 16 |
406-
var.length << 24)
407-
else:
408-
self.map_array[subindex].raw = (var.index << 16 |
409-
var.subindex << 8 |
410-
var.length)
411-
subindex += 1
412-
try:
413-
self.map_array[0].raw = len(self.map)
414-
except SdoAbortedError as e:
415-
# WORKAROUND for broken implementations: If the array
416-
# number-of-entries parameter is not writable, we have already
417-
# generated the required number of mappings above.
418-
if e.code != 0x06010002:
419-
# Abort codes other than "Attempt to write a read-only
420-
# object" should still be reported.
421-
raise
422-
self._update_data_size()
391+
try:
392+
self.map_array[0].raw = 0
393+
except SdoAbortedError:
394+
# WORKAROUND for broken implementations: If the array has a
395+
# fixed number of entries (count not writable), generate dummy
396+
# mappings for an invalid object 0x0000:00 to overwrite any
397+
# excess entries with all-zeros.
398+
self._fill_map(self.map_array[0].raw)
399+
subindex = 1
400+
for var in self.map:
401+
logger.info("Writing %s (0x%X:%d, %d bits) to PDO map",
402+
var.name, var.index, var.subindex, var.length)
403+
if getattr(self.pdo_node.node, "curtis_hack", False): # Curtis HACK: mixed up field order
404+
self.map_array[subindex].raw = (var.index |
405+
var.subindex << 16 |
406+
var.length << 24)
407+
else:
408+
self.map_array[subindex].raw = (var.index << 16 |
409+
var.subindex << 8 |
410+
var.length)
411+
subindex += 1
412+
try:
413+
self.map_array[0].raw = len(self.map)
414+
except SdoAbortedError as e:
415+
# WORKAROUND for broken implementations: If the array
416+
# number-of-entries parameter is not writable, we have already
417+
# generated the required number of mappings above.
418+
if e.code != 0x06010002:
419+
# Abort codes other than "Attempt to write a read-only
420+
# object" should still be reported.
421+
raise
422+
self._update_data_size()
423423

424424
if self.enabled:
425425
self.com_record[1].raw = self.cob_id | (RTR_NOT_ALLOWED if not self.rtr_allowed else 0x0)
@@ -521,7 +521,7 @@ def remote_request(self) -> None:
521521
Silently ignore if not allowed.
522522
"""
523523
if self.enabled and self.rtr_allowed:
524-
self.pdo_node.network.send_message(self.cob_id, None, remote=True)
524+
self.pdo_node.network.send_message(self.cob_id, bytes(), remote=True)
525525

526526
def wait_for_reception(self, timeout: float = 10) -> float:
527527
"""Wait for the next transmit PDO.
@@ -600,7 +600,7 @@ def set_data(self, data: bytes):
600600
cur_msg_data = cur_msg_data & bitwise_not
601601
# Set the new data on the correct position
602602
data = (data << bit_offset) | cur_msg_data
603-
data = od_struct.pack_into(self.pdo_parent.data, byte_offset, data)
603+
od_struct.pack_into(self.pdo_parent.data, byte_offset, data)
604604
else:
605605
self.pdo_parent.data[byte_offset:byte_offset + len(data)] = data
606606

test/test_pdo.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ def test_bit_mapping(self):
5555
self.assertEqual(node.tpdo[0x2002].raw, 0xf)
5656
self.assertEqual(node.pdo[0x1600][0x2002].raw, 0xf)
5757

58+
def test_save_pdo(self):
59+
node = canopen.Node(1, EDS_PATH)
60+
node.tpdo.save()
61+
node.rpdo.save()
62+
5863

5964
if __name__ == "__main__":
6065
unittest.main()

0 commit comments

Comments
 (0)