Skip to content

Commit

Permalink
Merge pull request #719 from ianmcorvidae/ignore-nodes
Browse files Browse the repository at this point in the history
Support setting nodes ignored in nodedb (with 2.5.13+ firmware)
  • Loading branch information
ianmcorvidae authored Dec 21, 2024
2 parents a765bcc + 4b6d7a8 commit 29f355b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 0 deletions.
20 changes: 20 additions & 0 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,16 @@ def onConnected(interface):
waitForAckNak = True
interface.getNode(args.dest, False, **getNode_kwargs).removeFavorite(args.remove_favorite_node)

if args.set_ignored_node:
closeNow = True
waitForAckNak = True
interface.getNode(args.dest, False, **getNode_kwargs).setIgnored(args.set_ignored_node)

if args.remove_ignored_node:
closeNow = True
waitForAckNak = True
interface.getNode(args.dest, False, **getNode_kwargs).removeIgnored(args.remove_ignored_node)

if args.reset_nodedb:
closeNow = True
waitForAckNak = True
Expand Down Expand Up @@ -1722,6 +1732,16 @@ def addRemoteAdminArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentPars
help="Tell the destination node to set the specified node to be un-favorited on the NodeDB on the device, by number or ID",
metavar="!xxxxxxxx"
)
group.add_argument(
"--set-ignored-node",
help="Tell the destination node to set the specified node to be ignored on the NodeDB on the devicein its DB, by number or ID",
metavar="!xxxxxxxx"
)
group.add_argument(
"--remove-ignored-node",
help="Tell the destination node to set the specified node to be un-ignored on the NodeDB on the device, by number or ID",
metavar="!xxxxxxxx"
)
group.add_argument(
"--reset-nodedb",
help="Tell the destination node to clear its list of nodes",
Expand Down
36 changes: 36 additions & 0 deletions meshtastic/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,42 @@ def removeFavorite(self, nodeId: Union[int, str]):
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)

def setIgnored(self, nodeId: Union[int, str]):
"""Tell the node to set the specified node ID to be ignored on the NodeDB on the device"""
self.ensureSessionKey()
if isinstance(nodeId, str):
if nodeId.startswith("!"):
nodeId = int(nodeId[1:], 16)
else:
nodeId = int(nodeId)

p = admin_pb2.AdminMessage()
p.set_ignored_node = nodeId

if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)

def removeIgnored(self, nodeId: Union[int, str]):
"""Tell the node to set the specified node ID to be un-ignored on the NodeDB on the device"""
self.ensureSessionKey()
if isinstance(nodeId, str):
if nodeId.startswith("!"):
nodeId = int(nodeId[1:], 16)
else:
nodeId = int(nodeId)

p = admin_pb2.AdminMessage()
p.remove_ignored_node = nodeId

if self == self.iface.localNode:
onResponse = None
else:
onResponse = self.onAckNak
return self._sendAdmin(p, onResponse=onResponse)

def resetNodeDb(self):
"""Tell the node to reset its list of nodes."""
self.ensureSessionKey()
Expand Down
30 changes: 30 additions & 0 deletions meshtastic/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2683,3 +2683,33 @@ def test_remove_favorite_node():
main()

mocked_node.removeFavorite.assert_called_once_with("!12345678")

@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_set_ignored_node():
"""Test --set-ignored-node node"""
sys.argv = ["", "--set-ignored-node", "!12345678"]
mt_config.args = sys.argv
mocked_node = MagicMock(autospec=Node)
iface = MagicMock(autospec=SerialInterface)
iface.getNode.return_value = mocked_node
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
main()

mocked_node.setIgnored.assert_called_once_with("!12345678")


@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_remove_ignored_node():
"""Test --remove-ignored-node node"""
sys.argv = ["", "--remove-ignored-node", "!12345678"]
mt_config.args = sys.argv
mocked_node = MagicMock(autospec=Node)
iface = MagicMock(autospec=SerialInterface)
iface.getNode.return_value = mocked_node
mocked_node.iface = iface
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
main()

mocked_node.removeIgnored.assert_called_once_with("!12345678")
27 changes: 27 additions & 0 deletions meshtastic/tests/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,33 @@ def test_remove_favorite(favorite):
iface.sendData.assert_called_once()


@pytest.mark.unit
@pytest.mark.parametrize("ignored", ["!1dec0ded", 502009325])
def test_set_ignored(ignored):
"""Test setFavorite"""
iface = MagicMock(autospec=SerialInterface)
node = Node(iface, 12345678)
amesg = admin_pb2.AdminMessage()
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
node.setIgnored(ignored)
assert amesg.set_ignored_node == 502009325
iface.sendData.assert_called_once()


@pytest.mark.unit
@pytest.mark.parametrize("ignored", ["!1dec0ded", 502009325])
def test_remove_ignored(ignored):
"""Test setFavorite"""
iface = MagicMock(autospec=SerialInterface)
node = Node(iface, 12345678)
amesg = admin_pb2.AdminMessage()
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
node.removeIgnored(ignored)

assert amesg.remove_ignored_node == 502009325
iface.sendData.assert_called_once()


# TODO
# @pytest.mark.unitslow
# def test_waitForConfig():
Expand Down

0 comments on commit 29f355b

Please sign in to comment.