Skip to content

Commit df191e1

Browse files
authored
Merge pull request #713 from esev/favorite
Support setting/removing nodes as favorites
2 parents 843abe5 + 18ac0d6 commit df191e1

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

meshtastic/__main__.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,16 @@ def onConnected(interface):
444444
waitForAckNak = True
445445
interface.getNode(args.dest, False, **getNode_kwargs).removeNode(args.remove_node)
446446

447+
if args.set_favorite_node:
448+
closeNow = True
449+
waitForAckNak = True
450+
interface.getNode(args.dest, False, **getNode_kwargs).setFavorite(args.set_favorite_node)
451+
452+
if args.remove_favorite_node:
453+
closeNow = True
454+
waitForAckNak = True
455+
interface.getNode(args.dest, False, **getNode_kwargs).removeFavorite(args.remove_favorite_node)
456+
447457
if args.reset_nodedb:
448458
closeNow = True
449459
waitForAckNak = True
@@ -1702,6 +1712,16 @@ def addRemoteAdminArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentPars
17021712
help="Tell the destination node to remove a specific node from its DB, by node number or ID",
17031713
metavar="!xxxxxxxx"
17041714
)
1715+
group.add_argument(
1716+
"--set-favorite-node",
1717+
help="Tell the destination node to set the specified node to be favorited on the NodeDB on the devicein its DB, by number or ID",
1718+
metavar="!xxxxxxxx"
1719+
)
1720+
group.add_argument(
1721+
"--remove-favorite-node",
1722+
help="Tell the destination node to set the specified node to be un-favorited on the NodeDB on the device, by number or ID",
1723+
metavar="!xxxxxxxx"
1724+
)
17051725
group.add_argument(
17061726
"--reset-nodedb",
17071727
help="Tell the destination node to clear its list of nodes",

meshtastic/node.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,42 @@ def removeNode(self, nodeId: Union[int, str]):
668668
onResponse = self.onAckNak
669669
return self._sendAdmin(p, onResponse=onResponse)
670670

671+
def setFavorite(self, nodeId: Union[int, str]):
672+
"""Tell the node to set the specified node ID to be favorited on the NodeDB on the device"""
673+
self.ensureSessionKey()
674+
if isinstance(nodeId, str):
675+
if nodeId.startswith("!"):
676+
nodeId = int(nodeId[1:], 16)
677+
else:
678+
nodeId = int(nodeId)
679+
680+
p = admin_pb2.AdminMessage()
681+
p.set_favorite_node = nodeId
682+
683+
if self == self.iface.localNode:
684+
onResponse = None
685+
else:
686+
onResponse = self.onAckNak
687+
return self._sendAdmin(p, onResponse=onResponse)
688+
689+
def removeFavorite(self, nodeId: Union[int, str]):
690+
"""Tell the node to set the specified node ID to be un-favorited on the NodeDB on the device"""
691+
self.ensureSessionKey()
692+
if isinstance(nodeId, str):
693+
if nodeId.startswith("!"):
694+
nodeId = int(nodeId[1:], 16)
695+
else:
696+
nodeId = int(nodeId)
697+
698+
p = admin_pb2.AdminMessage()
699+
p.remove_favorite_node = nodeId
700+
701+
if self == self.iface.localNode:
702+
onResponse = None
703+
else:
704+
onResponse = self.onAckNak
705+
return self._sendAdmin(p, onResponse=onResponse)
706+
671707
def resetNodeDb(self):
672708
"""Tell the node to reset its list of nodes."""
673709
self.ensureSessionKey()

meshtastic/tests/test_main.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,3 +2652,34 @@ def my_sleep(amount):
26522652
out, err = capsys.readouterr()
26532653
assert re.search(r"Connected to radio", out, re.MULTILINE)
26542654
assert err == ""
2655+
2656+
2657+
@pytest.mark.unit
2658+
@pytest.mark.usefixtures("reset_mt_config")
2659+
def test_set_favorite_node():
2660+
"""Test --set-favorite-node node"""
2661+
sys.argv = ["", "--set-favorite-node", "!12345678"]
2662+
mt_config.args = sys.argv
2663+
mocked_node = MagicMock(autospec=Node)
2664+
iface = MagicMock(autospec=SerialInterface)
2665+
iface.getNode.return_value = mocked_node
2666+
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
2667+
main()
2668+
2669+
mocked_node.setFavorite.assert_called_once_with("!12345678")
2670+
2671+
2672+
@pytest.mark.unit
2673+
@pytest.mark.usefixtures("reset_mt_config")
2674+
def test_remove_favorite_node():
2675+
"""Test --remove-favorite-node node"""
2676+
sys.argv = ["", "--remove-favorite-node", "!12345678"]
2677+
mt_config.args = sys.argv
2678+
mocked_node = MagicMock(autospec=Node)
2679+
iface = MagicMock(autospec=SerialInterface)
2680+
iface.getNode.return_value = mocked_node
2681+
mocked_node.iface = iface
2682+
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
2683+
main()
2684+
2685+
mocked_node.removeFavorite.assert_called_once_with("!12345678")

meshtastic/tests/test_node.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import pytest
88

9-
from ..protobuf import localonly_pb2, config_pb2
9+
from ..protobuf import admin_pb2, localonly_pb2, config_pb2
1010
from ..protobuf.channel_pb2 import Channel # pylint: disable=E0611
1111
from ..node import Node
1212
from ..serial_interface import SerialInterface
@@ -1426,6 +1426,33 @@ def test_requestChannels_non_localNode_starting_index(caplog):
14261426
# assert err == ''
14271427

14281428

1429+
@pytest.mark.unit
1430+
@pytest.mark.parametrize("favorite", ["!1dec0ded", 502009325])
1431+
def test_set_favorite(favorite):
1432+
"""Test setFavorite"""
1433+
iface = MagicMock(autospec=SerialInterface)
1434+
node = Node(iface, 12345678)
1435+
amesg = admin_pb2.AdminMessage()
1436+
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
1437+
node.setFavorite(favorite)
1438+
assert amesg.set_favorite_node == 502009325
1439+
iface.sendData.assert_called_once()
1440+
1441+
1442+
@pytest.mark.unit
1443+
@pytest.mark.parametrize("favorite", ["!1dec0ded", 502009325])
1444+
def test_remove_favorite(favorite):
1445+
"""Test setFavorite"""
1446+
iface = MagicMock(autospec=SerialInterface)
1447+
node = Node(iface, 12345678)
1448+
amesg = admin_pb2.AdminMessage()
1449+
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
1450+
node.removeFavorite(favorite)
1451+
1452+
assert amesg.remove_favorite_node == 502009325
1453+
iface.sendData.assert_called_once()
1454+
1455+
14291456
# TODO
14301457
# @pytest.mark.unitslow
14311458
# def test_waitForConfig():

0 commit comments

Comments
 (0)