Skip to content
Merged
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
23 changes: 20 additions & 3 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,12 +674,16 @@ def onConnected(interface):
closeNow = True
export_config(interface)

if args.seturl:
if args.ch_set_url:
closeNow = True
interface.getNode(args.dest, **getNode_kwargs).setURL(args.seturl)
interface.getNode(args.dest, **getNode_kwargs).setURL(args.ch_set_url, addOnly=False)

# handle changing channels

if args.ch_add_url:
closeNow = True
interface.getNode(args.dest, **getNode_kwargs).setURL(args.ch_add_url, addOnly=True)

if args.ch_add:
channelIndex = mt_config.channel_index
if channelIndex is not None:
Expand Down Expand Up @@ -1443,7 +1447,20 @@ def addConfigArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
"--set-ham", help="Set licensed Ham ID and turn off encryption", action="store"
)

group.add_argument("--seturl", help="Set a channel URL", action="store")
group.add_argument(
"--ch-set-url", "--seturl",
help="Set all channels and set LoRa config from a supplied URL",
metavar="URL",
action="store"
)

group.add_argument(
"--ch-add-url",
help="Add secondary channels and set LoRa config from a supplied URL",
metavar="URL",
default=None,
)


return parser

Expand Down
57 changes: 39 additions & 18 deletions meshtastic/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,14 +337,19 @@ def getURL(self, includeAll: bool = True):
s = s.replace("=", "").replace("+", "-").replace("/", "_")
return f"https://meshtastic.org/e/#{s}"

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

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

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

i = 0
for chs in channelSet.settings:
ch = channel_pb2.Channel()
ch.role = (
channel_pb2.Channel.Role.PRIMARY
if i == 0
else channel_pb2.Channel.Role.SECONDARY
)
ch.index = i
ch.settings.CopyFrom(chs)
self.channels[ch.index] = ch
logging.debug(f"Channel i:{i} ch:{ch}")
self.writeChannel(ch.index)
i = i + 1
if addOnly:
# Add new channels with names not already present
# Don't change existing channels
for chs in channelSet.settings:
channelExists = self.getChannelByName(chs.name)
if channelExists or chs.name == "":
print(f"Ignoring existing or empty channel \"{chs.name}\" from add URL")
continue
ch = self.getDisabledChannel()
if not ch:
our_exit("Warning: No free channels were found")
ch.settings.CopyFrom(chs)
ch.role = channel_pb2.Channel.Role.SECONDARY
print(f"Adding new channel '{chs.name}' to device")
self.writeChannel(ch.index)
else:
i = 0
for chs in channelSet.settings:
ch = channel_pb2.Channel()
ch.role = (
channel_pb2.Channel.Role.PRIMARY
if i == 0
else channel_pb2.Channel.Role.SECONDARY
)
ch.index = i
ch.settings.CopyFrom(chs)
self.channels[ch.index] = ch
logging.debug(f"Channel i:{i} ch:{ch}")
self.writeChannel(ch.index)
i = i + 1

p = admin_pb2.AdminMessage()
p.set_config.lora.CopyFrom(channelSet.lora_config)
Expand Down
4 changes: 2 additions & 2 deletions meshtastic/tests/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def test_setURL_empty_url(capsys):
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
out, err = capsys.readouterr()
assert re.search(r"Warning: There were no settings.", out, re.MULTILINE)
assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE)
assert err == ""


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


Expand Down
Loading