Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions canopen/node/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class BaseNode:
"""A CANopen node.

:param node_id:
Node ID (set to None or 0 if specified by object dictionary)
Node ID (set to 0 if specified by object dictionary)
:param object_dictionary:
Object dictionary as either a path to a file, an ``ObjectDictionary``
or a file like object.
Expand All @@ -25,7 +25,9 @@ def __init__(
object_dictionary = import_od(object_dictionary, node_id)
self.object_dictionary = object_dictionary

self.id = node_id or self.object_dictionary.node_id
self.id = node_id or object_dictionary.node_id or 0
if not self.id or not 1 <= self.id <= 127:
Comment thread
acolomb marked this conversation as resolved.
Outdated
raise ValueError("No valid Node ID provided, %r not in range 1..127")
Comment thread
acolomb marked this conversation as resolved.
Outdated

def has_network(self) -> bool:
"""Check whether the node has been associated to a network."""
Expand Down
15 changes: 15 additions & 0 deletions canopen/node/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@


class LocalNode(BaseNode):
"""Local CANopen node implementing essential communication services.

This does not provide a full-fledged communication logic stack, but needs
additional application logic to wire up the various services, such as
triggering PDO transmissions according to their communication parameters.

Notable exceptions are a local data store for SDO server access, and using
the Heartbeat Producer Time parameter to control Heartbeat transmission.

:param node_id:
Node ID (set to 0 if specified by object dictionary)
:param object_dictionary:
Object dictionary as either a path to a file, an ``ObjectDictionary``
or a file like object.
"""

def __init__(
self,
Expand Down
2 changes: 1 addition & 1 deletion canopen/node/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class RemoteNode(BaseNode):
"""A CANopen remote node.

:param node_id:
Node ID (set to None or 0 if specified by object dictionary)
Node ID (set to 0 if specified by object dictionary)
:param object_dictionary:
Object dictionary as either a path to a file, an ``ObjectDictionary``
or a file like object.
Expand Down
19 changes: 19 additions & 0 deletions test/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,25 @@ def count_subscribers(network: canopen.Network) -> int:
return sum(len(n) for n in network.subscribers.values())


class TestBaseNode(unittest.TestCase):

def test_valid_node_id(self):
node = canopen.node.base.BaseNode(1, canopen.ObjectDictionary())
self.assertEqual(node.id, 1)

def test_valid_node_id_from_od(self):
od = canopen.ObjectDictionary()
od.node_id = 2
node = canopen.node.base.BaseNode(0, od)
self.assertEqual(node.id, 2)

def test_invalid_node_id(self):
with self.assertRaises(ValueError):
_ = canopen.node.base.BaseNode(0, canopen.ObjectDictionary())
with self.assertRaises(ValueError):
_ = canopen.node.base.BaseNode(128, canopen.ObjectDictionary())


class TestLocalNode(unittest.TestCase):

@classmethod
Expand Down
Loading