Skip to content

Commit f41ef04

Browse files
authored
Merge pull request #708 from mikeymakesit/add-channel
Add new channels from an add URL with the new --ch-add-url option
2 parents 985366c + 84bec5a commit f41ef04

File tree

3 files changed

+61
-23
lines changed

3 files changed

+61
-23
lines changed

meshtastic/__main__.py

+20-3
Original file line numberDiff line numberDiff line change
@@ -716,12 +716,16 @@ def onConnected(interface):
716716
closeNow = True
717717
export_config(interface)
718718

719-
if args.seturl:
719+
if args.ch_set_url:
720720
closeNow = True
721-
interface.getNode(args.dest, **getNode_kwargs).setURL(args.seturl)
721+
interface.getNode(args.dest, **getNode_kwargs).setURL(args.ch_set_url, addOnly=False)
722722

723723
# handle changing channels
724724

725+
if args.ch_add_url:
726+
closeNow = True
727+
interface.getNode(args.dest, **getNode_kwargs).setURL(args.ch_add_url, addOnly=True)
728+
725729
if args.ch_add:
726730
channelIndex = mt_config.channel_index
727731
if channelIndex is not None:
@@ -1515,7 +1519,20 @@ def addConfigArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
15151519
"--set-ham", help="Set licensed Ham ID and turn off encryption", action="store"
15161520
)
15171521

1518-
group.add_argument("--seturl", help="Set a channel URL", action="store")
1522+
group.add_argument(
1523+
"--ch-set-url", "--seturl",
1524+
help="Set all channels and set LoRa config from a supplied URL",
1525+
metavar="URL",
1526+
action="store"
1527+
)
1528+
1529+
group.add_argument(
1530+
"--ch-add-url",
1531+
help="Add secondary channels and set LoRa config from a supplied URL",
1532+
metavar="URL",
1533+
default=None,
1534+
)
1535+
15191536

15201537
return parser
15211538

meshtastic/node.py

+39-18
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,19 @@ def getURL(self, includeAll: bool = True):
337337
s = s.replace("=", "").replace("+", "-").replace("/", "_")
338338
return f"https://meshtastic.org/e/#{s}"
339339

340-
def setURL(self, url):
340+
def setURL(self, url: str, addOnly: bool = False):
341341
"""Set mesh network URL"""
342-
if self.localConfig is None:
343-
our_exit("Warning: No Config has been read")
342+
if self.localConfig is None or self.channels is None:
343+
our_exit("Warning: config or channels not loaded")
344344

345345
# URLs are of the form https://meshtastic.org/d/#{base64_channel_set}
346346
# Split on '/#' to find the base64 encoded channel settings
347-
splitURL = url.split("/#")
347+
if addOnly:
348+
splitURL = url.split("/?add=true#")
349+
else:
350+
splitURL = url.split("/#")
351+
if len(splitURL) == 1:
352+
our_exit(f"Warning: Invalid URL '{url}'")
348353
b64 = splitURL[-1]
349354

350355
# We normally strip padding to make for a shorter URL, but the python parser doesn't like
@@ -361,20 +366,36 @@ def setURL(self, url):
361366
if len(channelSet.settings) == 0:
362367
our_exit("Warning: There were no settings.")
363368

364-
i = 0
365-
for chs in channelSet.settings:
366-
ch = channel_pb2.Channel()
367-
ch.role = (
368-
channel_pb2.Channel.Role.PRIMARY
369-
if i == 0
370-
else channel_pb2.Channel.Role.SECONDARY
371-
)
372-
ch.index = i
373-
ch.settings.CopyFrom(chs)
374-
self.channels[ch.index] = ch
375-
logging.debug(f"Channel i:{i} ch:{ch}")
376-
self.writeChannel(ch.index)
377-
i = i + 1
369+
if addOnly:
370+
# Add new channels with names not already present
371+
# Don't change existing channels
372+
for chs in channelSet.settings:
373+
channelExists = self.getChannelByName(chs.name)
374+
if channelExists or chs.name == "":
375+
print(f"Ignoring existing or empty channel \"{chs.name}\" from add URL")
376+
continue
377+
ch = self.getDisabledChannel()
378+
if not ch:
379+
our_exit("Warning: No free channels were found")
380+
ch.settings.CopyFrom(chs)
381+
ch.role = channel_pb2.Channel.Role.SECONDARY
382+
print(f"Adding new channel '{chs.name}' to device")
383+
self.writeChannel(ch.index)
384+
else:
385+
i = 0
386+
for chs in channelSet.settings:
387+
ch = channel_pb2.Channel()
388+
ch.role = (
389+
channel_pb2.Channel.Role.PRIMARY
390+
if i == 0
391+
else channel_pb2.Channel.Role.SECONDARY
392+
)
393+
ch.index = i
394+
ch.settings.CopyFrom(chs)
395+
self.channels[ch.index] = ch
396+
logging.debug(f"Channel i:{i} ch:{ch}")
397+
self.writeChannel(ch.index)
398+
i = i + 1
378399

379400
p = admin_pb2.AdminMessage()
380401
p.set_config.lora.CopyFrom(channelSet.lora_config)

meshtastic/tests/test_node.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ def test_setURL_empty_url(capsys):
270270
assert pytest_wrapped_e.type == SystemExit
271271
assert pytest_wrapped_e.value.code == 1
272272
out, err = capsys.readouterr()
273-
assert re.search(r"Warning: There were no settings.", out, re.MULTILINE)
273+
assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE)
274274
assert err == ""
275275

276276

@@ -304,7 +304,7 @@ def test_setURL_valid_URL_but_no_settings(capsys):
304304
assert pytest_wrapped_e.type == SystemExit
305305
assert pytest_wrapped_e.value.code == 1
306306
out, err = capsys.readouterr()
307-
assert re.search(r"Warning: There were no settings", out, re.MULTILINE)
307+
assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE)
308308
assert err == ""
309309

310310

0 commit comments

Comments
 (0)