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
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:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The not self.id check (catching 0) is already a subset of not (1 <= self.id <= 127), since 0 is outside that range. The condition can be simplified to:

if not (1 <= self.id <= 127):

raise ValueError("No valid Node ID provided, %r not in range 1..127")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The format specifier %r is used in the string but no value is passed, so self.id will never appear in the error message. This should be:

raise ValueError("No valid Node ID provided, %r not in range 1..127" % self.id)

or using an f-string:

raise ValueError(f"No valid Node ID provided, {self.id!r} not in range 1..127")


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