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
30 changes: 26 additions & 4 deletions meshtastic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ def onConnected(interface):
print("Connected to radio")

if args.setlat or args.setlon or args.setalt:
if args.dest != BROADCAST_ADDR:
print("Setting latitude, longitude, and altitude of remote nodes is not supported.")
return
closeNow = True

alt = 0
Expand Down Expand Up @@ -599,6 +602,9 @@ def onConnected(interface):
print("Writing modified configuration to device")

if args.export_config:
if args.dest != BROADCAST_ADDR:
print("Exporting configuration of remote nodes is not supported.")
return
# export the configuration (the opposite of '--configure')
closeNow = True
export_config(interface)
Expand Down Expand Up @@ -801,10 +807,14 @@ def setSimpleConfig(modem_preset):
return
interface.showNodes()

if args.qr:
if args.qr or args.qr_all:
closeNow = True
url = interface.localNode.getURL(includeAll=False)
print(f"Primary channel URL {url}")
url = interface.getNode(args.dest, True).getURL(includeAll=args.qr_all)
if args.qr_all:
urldesc = "Complete URL (includes all channels)"
else:
urldesc = "Primary channel URL"
print(f"{urldesc}: {url}")
qr = pyqrcode.create(url)
print(qr.terminal())

Expand All @@ -813,6 +823,9 @@ def setSimpleConfig(modem_preset):

have_tunnel = platform.system() == "Linux"
if have_tunnel and args.tunnel:
if args.dest != BROADCAST_ADDR:
print("A tunnel can only be created using the local node.")
return
# pylint: disable=C0415
from . import tunnel

Expand Down Expand Up @@ -1154,7 +1167,16 @@ def initParser():

group.add_argument(
"--qr",
help="Display the QR code that corresponds to the current channel",
help=(
"Display a QR code for the node's primary channel (or all channels with --qr-all). "
"Also shows the shareable channel URL."
),
action="store_true",
)

group.add_argument(
"--qr-all",
help="Display a QR code and URL for all of the node's channels.",
action="store_true",
)

Expand Down
2 changes: 2 additions & 0 deletions meshtastic/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ def getURL(self, includeAll: bool = True):
):
channelSet.settings.append(c.settings)

if len(self.localConfig.ListFields()) == 0:
self.requestConfig(self.localConfig.DESCRIPTOR.fields_by_name.get('lora'))
channelSet.lora_config.CopyFrom(self.localConfig.lora)
some_bytes = channelSet.SerializeToString()
s = base64.urlsafe_b64encode(some_bytes).decode("ascii")
Expand Down
5 changes: 4 additions & 1 deletion meshtastic/tests/test_mesh_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import pytest

from .. import mesh_pb2, BROADCAST_ADDR, LOCAL_ADDR
from .. import mesh_pb2, config_pb2, BROADCAST_ADDR, LOCAL_ADDR
from ..mesh_interface import MeshInterface
from ..node import Node

Expand Down Expand Up @@ -36,12 +36,15 @@ def test_MeshInterface(capsys):
"lastHeard": 1640204888,
}


iface.nodes = {NODE_ID: node}
iface.nodesByNum = {NODE_NUM: node}

myInfo = MagicMock()
iface.myInfo = myInfo

iface.localNode.localConfig.lora.CopyFrom(config_pb2.Config.LoRaConfig())

iface.showInfo()
iface.localNode.showInfo()
iface.showNodes()
Expand Down
37 changes: 21 additions & 16 deletions meshtastic/tests/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import pytest

# from ..admin_pb2 import AdminMessage
from .. import localonly_pb2, config_pb2
from ..channel_pb2 import Channel # pylint: disable=E0611
from ..node import Node
from ..serial_interface import SerialInterface
Expand All @@ -19,21 +19,26 @@
# from ..util import Timeout


# TODO
# @pytest.mark.unit
# def test_node(capsys):
# """Test that we can instantiate a Node"""
# anode = Node('foo', 'bar')
# radioConfig = RadioConfig()
# anode.radioConfig = radioConfig
# anode.showChannels()
# anode.showInfo()
# out, err = capsys.readouterr()
# assert re.search(r'Preferences', out)
# assert re.search(r'Channels', out)
# assert re.search(r'Primary channel URL', out)
# assert err == ''

@pytest.mark.unit
def test_node(capsys):
"""Test that we can instantiate a Node"""
iface = MagicMock(autospec=SerialInterface)
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, "bar", noProto=True)
lc = localonly_pb2.LocalConfig()
anode.localConfig = lc
lc.lora.CopyFrom(config_pb2.Config.LoRaConfig())
anode.moduleConfig = localonly_pb2.LocalModuleConfig()
anode.showInfo()
out, err = capsys.readouterr()
assert re.search(r'Preferences', out)
assert re.search(r'Module preferences', out)
assert re.search(r'Channels', out)
assert re.search(r'Primary channel URL', out)
assert not re.search(r'remote node', out)
assert err == ''

# TODO
# @pytest.mark.unit
Expand Down
2 changes: 2 additions & 0 deletions meshtastic/tests/test_serial_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest

from ..serial_interface import SerialInterface
from .. import config_pb2


@pytest.mark.unit
Expand All @@ -20,6 +21,7 @@ def test_SerialInterface_single_port(
):
"""Test that we can instantiate a SerialInterface with a single port"""
iface = SerialInterface(noProto=True)
iface.localNode.localConfig.lora.CopyFrom(config_pb2.Config.LoRaConfig())
iface.showInfo()
iface.localNode.showInfo()
iface.close()
Expand Down
2 changes: 2 additions & 0 deletions meshtastic/tests/test_tcp_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import pytest

from .. import config_pb2
from ..tcp_interface import TCPInterface


Expand All @@ -13,6 +14,7 @@ def test_TCPInterface(capsys):
"""Test that we can instantiate a TCPInterface"""
with patch("socket.socket") as mock_socket:
iface = TCPInterface(hostname="localhost", noProto=True)
iface.localNode.localConfig.lora.CopyFrom(config_pb2.Config.LoRaConfig())
iface.myConnect()
iface.showInfo()
iface.localNode.showInfo()
Expand Down