Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions canopen/pdo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from typing import Union

from canopen import node
from canopen.pdo.base import PdoBase, PdoMap, PdoMaps, PdoVariable
Expand Down Expand Up @@ -30,11 +31,18 @@ def __init__(self, node, rpdo, tpdo):
self.tx = tpdo.map

self.map = {}
# the object 0x1A00 equals to key '1' so we remove 1 from the key
for key, value in self.rx.items():
self.map[0x1A00 + (key - 1)] = value
self.map[0x1400 + (key - 1)] = value
for key, value in self.tx.items():
self.map[0x1600 + (key - 1)] = value
self.map[0x1800 + (key - 1)] = value

def __getitem__(self, key: Union[int, str]):
if isinstance(key, int):
if 0x1600 <= key <= 0x1600 + 511:
key = 0x1800 + (key - 0x1600)
elif 0x1A00 <= key <= 0x1A00 + 511:
key = 0x1400 + (key - 0x1A00)
return super().__getitem__(key)


class RPDO(PdoBase):
Expand Down
9 changes: 7 additions & 2 deletions canopen/pdo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ def __getitem__(self, key: Union[int, str]):
raise KeyError("PDO index zero requested for 1-based sequence")
if (
0 < key <= 512 # By PDO Index
or 0x1600 <= key <= 0x17FF # By RPDO ID (512)
or 0x1A00 <= key <= 0x1BFF # By TPDO ID (512)
or 0x1400 <= key <= 0x1BFF # By record ID
):
return self.map[key]
for pdo_map in self.map.values():
Expand Down Expand Up @@ -154,6 +153,8 @@ def __init__(self, com_offset, map_offset, pdo_node: PdoBase, cob_base=None):
:param pdo_node:
:param cob_base:
"""
self.com_offset = com_offset
self.map_offset = map_offset
self.maps: dict[int, PdoMap] = {}
for map_no in range(512):
if com_offset + map_no in pdo_node.node.object_dictionary:
Expand All @@ -167,6 +168,10 @@ def __init__(self, com_offset, map_offset, pdo_node: PdoBase, cob_base=None):
self.maps[map_no + 1] = new_map

def __getitem__(self, key: int) -> PdoMap:
if self.com_offset <= key <= self.com_offset + 511:
return self.maps[key - self.com_offset + 1]
if self.map_offset <= key <= self.map_offset + 511:
return self.maps[key - self.map_offset + 1]
return self.maps[key]

def __iter__(self) -> Iterator[int]:
Expand Down
22 changes: 22 additions & 0 deletions test/test_pdo.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ def test_pdo_getitem(self):
self.assertRaises(KeyError, lambda: node.pdo[0x1BFF])
self.assertRaises(KeyError, lambda: node.tpdo[0x1BFF])

def test_pdo_getitem_communication_records(self):
# Test PDO access by communication parameter record indices
node = self.node
rpdo_comm = node.rpdo[0x1400]
self.assertIsInstance(rpdo_comm, canopen.pdo.PdoMap)
self.assertIs(rpdo_comm, node.rpdo[1])
tpdo_comm = node.tpdo[0x1800]
self.assertIsInstance(tpdo_comm, canopen.pdo.PdoMap)
self.assertIs(tpdo_comm, node.tpdo[1])

# Test generic PDO with RPDO
pdo_rpdo_comm = node.pdo[0x1400]
self.assertIsInstance(pdo_rpdo_comm, canopen.pdo.PdoMap)

# Test generic PDO with TPDO
pdo_tpdo_comm = node.pdo[0x1800]
self.assertIsInstance(pdo_tpdo_comm, canopen.pdo.PdoMap)

# Verify the returned objects are the same as mapping record access
self.assertIs(node.rpdo[0x1400], node.rpdo[0x1600])
self.assertIs(node.tpdo[0x1800], node.tpdo[0x1A00])

def test_pdo_maps_iterate(self):
node = self.node
self.assertEqual(len(node.pdo), sum(1 for _ in node.pdo))
Expand Down