Skip to content

Add Ringtone and Canned Messages to --export-config and --configure #795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions example_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ owner_short: BOB

channel_url: https://www.meshtastic.org/e/#CgMSAQESCDgBQANIAVAe

canned_messages: Hi|Bye|Yes|No|Ok
ringtone: 24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p

location:
lat: 35.88888
lon: -93.88888
Expand Down
24 changes: 20 additions & 4 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,6 @@
print(f"Setting device owner short to {args.set_owner_short}")
interface.getNode(args.dest, False, **getNode_kwargs).setOwner(long_name=args.set_owner, short_name=args.set_owner_short)

# TODO: add to export-config and configure
if args.set_canned_message:
closeNow = True
waitForAckNak = True
Expand All @@ -371,7 +370,6 @@
args.set_canned_message
)

# TODO: add to export-config and configure
if args.set_ringtone:
closeNow = True
waitForAckNak = True
Expand Down Expand Up @@ -705,6 +703,16 @@
interface.getNode(args.dest, **getNode_kwargs).setURL(configuration["channelUrl"])
time.sleep(0.5)

if "canned_messages" in configuration:
print("Setting canned message messages to", configuration["canned_messages"])
interface.getNode(args.dest, **getNode_kwargs).set_canned_message(configuration["canned_messages"])
time.sleep(0.5)

Check warning on line 709 in meshtastic/__main__.py

View check run for this annotation

Codecov / codecov/patch

meshtastic/__main__.py#L707-L709

Added lines #L707 - L709 were not covered by tests

if "ringtone" in configuration:
print("Setting ringtone to", configuration["ringtone"])
interface.getNode(args.dest, **getNode_kwargs).set_ringtone(configuration["ringtone"])
time.sleep(0.5)

Check warning on line 714 in meshtastic/__main__.py

View check run for this annotation

Codecov / codecov/patch

meshtastic/__main__.py#L712-L714

Added lines #L712 - L714 were not covered by tests

if "location" in configuration:
alt = 0
lat = 0.0
Expand Down Expand Up @@ -928,12 +936,14 @@
if args.get_canned_message:
closeNow = True
print("")
interface.getNode(args.dest, **getNode_kwargs).get_canned_message()
messages = interface.getNode(args.dest, **getNode_kwargs).get_canned_message()
print(f"canned_plugin_message:{messages}")

if args.get_ringtone:
closeNow = True
print("")
interface.getNode(args.dest, **getNode_kwargs).get_ringtone()
ringtone = interface.getNode(args.dest, **getNode_kwargs).get_ringtone()
print(f"ringtone:{ringtone}")

if args.info:
print("")
Expand Down Expand Up @@ -1097,6 +1107,8 @@
owner_short = interface.getShortName()
channel_url = interface.localNode.getURL()
myinfo = interface.getMyNodeInfo()
canned_messages = interface.getCannedMessage()
ringtone = interface.getRingtone()
pos = myinfo.get("position")
lat = None
lon = None
Expand All @@ -1115,6 +1127,10 @@
configObj["channelUrl"] = channel_url
else:
configObj["channel_url"] = channel_url
if canned_messages:
configObj["canned_messages"] = canned_messages
if ringtone:
configObj["ringtone"] = ringtone
# lat and lon don't make much sense without the other (so fill with 0s), and alt isn't meaningful without both
if lat or lon:
configObj["location"] = {"lat": lat or float(0), "lon": lon or float(0)}
Expand Down
14 changes: 14 additions & 0 deletions meshtastic/mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,20 @@
return user.get("publicKey", None)
return None

def getCannedMessage(self):
"""Get canned message"""
node = self.localNode
if node is not None:
return node.get_canned_message()
return None

Check warning on line 1085 in meshtastic/mesh_interface.py

View check run for this annotation

Codecov / codecov/patch

meshtastic/mesh_interface.py#L1085

Added line #L1085 was not covered by tests

def getRingtone(self):
"""Get ringtone"""
node = self.localNode
if node is not None:
return node.get_ringtone()
return None

Check warning on line 1092 in meshtastic/mesh_interface.py

View check run for this annotation

Codecov / codecov/patch

meshtastic/mesh_interface.py#L1092

Added line #L1092 was not covered by tests

def _waitConnected(self, timeout=30.0):
"""Block until the initial node db download is complete, or timeout
and raise an exception"""
Expand Down
2 changes: 0 additions & 2 deletions meshtastic/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,6 @@ def get_ringtone(self):
if self.ringtonePart:
self.ringtone += self.ringtonePart

print(f"ringtone:{self.ringtone}")
logging.debug(f"ringtone:{self.ringtone}")
return self.ringtone

Expand Down Expand Up @@ -530,7 +529,6 @@ def get_canned_message(self):
if self.cannedPluginMessageMessages:
self.cannedPluginMessage += self.cannedPluginMessageMessages

print(f"canned_plugin_message:{self.cannedPluginMessage}")
logging.debug(f"canned_plugin_message:{self.cannedPluginMessage}")
return self.cannedPluginMessage

Expand Down
40 changes: 40 additions & 0 deletions meshtastic/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,44 @@ def test_main_get_canned_messages(capsys, caplog, iface_with_nodes):
assert err == ""
mo.assert_called()

@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_ringtone(capsys):
"""Test --set-ringtone"""
sys.argv = ["", "--set-ringtone", "foo,bar"]
mt_config.args = sys.argv

iface = MagicMock(autospec=SerialInterface)
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE)
assert re.search(r"Setting ringtone to foo,bar", out, re.MULTILINE)
assert err == ""
mo.assert_called()

@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_get_ringtone(capsys, caplog, iface_with_nodes):
"""Test --get-ringtone"""
sys.argv = ["", "--get-ringtone"]
mt_config.args = sys.argv

iface = iface_with_nodes
iface.devPath = "bar"

mocked_node = MagicMock(autospec=Node)
mocked_node.get_ringtone.return_value = "foo,bar"
iface.localNode = mocked_node

with caplog.at_level(logging.DEBUG):
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE)
assert re.search(r"ringtone:foo,bar", out, re.MULTILINE)
assert err == ""
mo.assert_called()

@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
Expand Down Expand Up @@ -1724,6 +1762,8 @@ def test_main_export_config(capsys):
mo.getLongName.return_value = "foo"
mo.getShortName.return_value = "oof"
mo.localNode.getURL.return_value = "bar"
mo.getCannedMessage.return_value = "foo|bar"
mo.getRingtone.return_value = "24:d=32,o=5"
mo.getMyNodeInfo().get.return_value = {
"latitudeI": 1100000000,
"longitudeI": 1200000000,
Expand Down
23 changes: 22 additions & 1 deletion meshtastic/tests/test_mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,28 @@ def test_getMyNodeInfo():
myinfo = iface.getMyNodeInfo()
assert myinfo == anode

@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_getCannedMessage():
"""Test MeshInterface.getCannedMessage()"""
iface = MeshInterface(noProto=True)
node = MagicMock()
node.get_canned_message.return_value = "Hi|Bye|Yes"
iface.localNode = node
result = iface.getCannedMessage()
assert result == "Hi|Bye|Yes"


@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_getRingtone():
"""Test MeshInterface.getRingtone()"""
iface = MeshInterface(noProto=True)
node = MagicMock()
node.get_ringtone.return_value = "foo,bar"
iface.localNode = node
result = iface.getRingtone()
assert result == "foo,bar"

@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
Expand All @@ -543,7 +565,6 @@ def test_generatePacketId(capsys):
assert err == ""
assert pytest_wrapped_e.type == MeshInterface.MeshInterfaceError


@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_fixupPosition_empty_pos():
Expand Down
Loading