From 8dbd6431f7e08d77cf1a397e65ee1ea45b1f51de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Fri, 17 Jun 2022 12:31:18 +0200 Subject: [PATCH] almost working --- TODO.md | 2 +- meshtastic/__init__.py | 2 +- meshtastic/__main__.py | 19 +++++------ meshtastic/mesh_interface.py | 20 +++++------- meshtastic/node.py | 63 ++++++++++++++++++++++++++---------- 5 files changed, 66 insertions(+), 40 deletions(-) diff --git a/TODO.md b/TODO.md index 46cebc6..ed3c177 100644 --- a/TODO.md +++ b/TODO.md @@ -34,7 +34,7 @@ Basic functionality is complete now. - DONE add fromId and toId to received messages dictionaries - make command line options for displaying/changing config - update nodedb as nodes change -- radioConfig - getter/setter syntax: https://www.python-course.eu/python3_properties.php +- localConfig - getter/setter syntax: https://www.python-course.eu/python3_properties.php - let user change radio params via commandline options - keep nodedb up-to-date based on received MeshPackets - handle radio reboots and redownload db when that happens. Look for a special FromRadio.rebooted packet diff --git a/meshtastic/__init__.py b/meshtastic/__init__.py index be32b51..65ae6d3 100644 --- a/meshtastic/__init__.py +++ b/meshtastic/__init__.py @@ -7,7 +7,7 @@ Source code on [github](https://github.com/meshtastic/Meshtastic-python) properties of SerialInterface: -- radioConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to +- localConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to the device. - nodes - The database of received nodes. Includes always up-to-date location and username information for each node in the mesh. This is a read-only datastructure. diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 8c50afe..5c41d95 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -183,7 +183,7 @@ def onConnected(interface): alt = 0 lat = 0.0 lon = 0.0 - prefs = interface.localNode.radioConfig.preferences + prefs = interface.localNode.localConfig if args.setalt: alt = int(args.setalt) prefs.fixed_position = True @@ -224,7 +224,7 @@ def onConnected(interface): if args.pos_fields: # If --pos-fields invoked with args, set position fields closeNow = True - prefs = interface.getNode(args.dest).radioConfig.preferences + prefs = interface.getNode(args.dest).localConfig allFields = 0 try: @@ -246,7 +246,8 @@ def onConnected(interface): elif args.pos_fields is not None: # If --pos-fields invoked without args, read and display current value closeNow = True - prefs = interface.getNode(args.dest).radioConfig.preferences + prefs = interface.getNode(args.dest).localConfig + ces fieldNames = [] for bit in config_pb2.PositionFlags.values(): @@ -326,7 +327,7 @@ def onConnected(interface): # handle settings if args.set: closeNow = True - prefs = interface.getNode(args.dest).radioConfig.preferences + prefs = interface.getNode(args.dest).localConfig # Handle the int/float/bool arguments for pref in args.set: @@ -364,7 +365,7 @@ def onConnected(interface): alt = 0 lat = 0.0 lon = 0.0 - prefs = interface.localNode.radioConfig.preferences + prefs = interface.localNode.localConfig if 'alt' in configuration['location']: alt = int(configuration['location']['alt']) @@ -383,14 +384,14 @@ def onConnected(interface): interface.localNode.writeConfig() if 'user_prefs' in configuration: - prefs = interface.getNode(args.dest).radioConfig.preferences + prefs = interface.getNode(args.dest).localConfig for pref in configuration['user_prefs']: setPref(prefs, pref, str(configuration['user_prefs'][pref])) print("Writing modified preferences to device") interface.getNode(args.dest).writeConfig() if 'userPrefs' in configuration: - prefs = interface.getNode(args.dest).radioConfig.preferences + prefs = interface.getNode(args.dest).localConfig for pref in configuration['userPrefs']: setPref(prefs, pref, str(configuration['userPrefs'][pref])) print("Writing modified preferences to device") @@ -539,7 +540,7 @@ def onConnected(interface): if args.get: closeNow = True - prefs = interface.getNode(args.dest).radioConfig.preferences + prefs = interface.getNode(args.dest).localConfig # Handle the int/float/bool arguments for pref in args.get: @@ -628,7 +629,7 @@ def export_config(interface): if alt: config += f" alt: {alt}\n" config += "\n" - preferences = f'{interface.localNode.radioConfig.preferences}' + preferences = f'{interface.localNode.localConfig}' prefs = preferences.splitlines() if prefs: if Globals.getInstance().get_camel_case(): diff --git a/meshtastic/mesh_interface.py b/meshtastic/mesh_interface.py index 1be5b60..6db4653 100644 --- a/meshtastic/mesh_interface.py +++ b/meshtastic/mesh_interface.py @@ -422,10 +422,8 @@ class MeshInterface: """We need to send a heartbeat message to the device every X seconds""" def callback(): self.heartbeatTimer = None - # TODO - # prefs = self.localNode.radioConfig.preferences - #i = prefs.phone_timeout_secs / 2 - i = 0 + prefs = self.localNode.localConfig + i = prefs.power.ls_secs / 2 logging.debug(f"Sending heartbeat, interval {i}") if i != 0: self.heartbeatTimer = threading.Timer(i, callback) @@ -543,20 +541,18 @@ class MeshInterface: self._startConfig() # redownload the node db etc... elif fromRadio.config: - logging.debug("Hey! We got some configs") if fromRadio.config.HasField("device"): - logging.debug("device!") - # TODO: do something with this config + self.localNode.localConfig.device.CopyFrom(fromRadio.config.device) elif fromRadio.config.HasField("position"): - logging.debug("position!") + self.localNode.localConfig.position.CopyFrom(fromRadio.config.position) elif fromRadio.config.HasField("power"): - logging.debug("power!") + self.localNode.localConfig.power.CopyFrom(fromRadio.config.power) elif fromRadio.config.HasField("wifi"): - logging.debug("wifi!") + self.localNode.localConfig.wifi.CopyFrom(fromRadio.config.wifi) elif fromRadio.config.HasField("display"): - logging.debug("display!") + self.localNode.localConfig.display.CopyFrom(fromRadio.config.display) elif fromRadio.config.HasField("lora"): - logging.debug("lora!") + self.localNode.localConfig.lora.CopyFrom(fromRadio.config.lora) else: logging.debug("Unexpected FromRadio payload") diff --git a/meshtastic/node.py b/meshtastic/node.py index ac14e7b..ee4b11c 100644 --- a/meshtastic/node.py +++ b/meshtastic/node.py @@ -5,22 +5,21 @@ import logging import base64 import time from google.protobuf.json_format import MessageToJson -from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2 +from meshtastic import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2, localonly_pb2 from meshtastic.util import pskToString, stripnl, Timeout, our_exit, fromPSK class Node: """A model of a (local or remote) node in the mesh - Includes methods for radioConfig and channels + Includes methods for localConfig and channels """ def __init__(self, iface, nodeNum, noProto=False): """Constructor""" self.iface = iface self.nodeNum = nodeNum - self.radioConfig = None - self.partialConfig = None + self.localConfig = localonly_pb2.LocalConfig() self.channels = None self._timeout = Timeout(maxSecs=300) self.partialChannels = None @@ -55,15 +54,15 @@ class Node: def showInfo(self): """Show human readable description of our node""" prefs = "" - if self.radioConfig and self.radioConfig.preferences: - prefs = stripnl(MessageToJson(self.radioConfig.preferences)) + if self.localConfig: + prefs = stripnl(MessageToJson(self.localConfig)) print(f"Preferences: {prefs}\n") self.showChannels() def requestConfig(self): """Send regular MeshPackets to ask for settings and channels.""" logging.debug(f"requestConfig for nodeNum:{self.nodeNum}") - self.radioConfig = None + self.localConfig = localonly_pb2.LocalConfig() self.channels = None self.partialChannels = [] # We keep our channels in a temp array until finished @@ -85,18 +84,48 @@ class Node: def waitForConfig(self, attribute='channels'): """Block until radio config is received. Returns True if config has been received.""" - return self._timeout.waitForSet(self, attrs=('config', attribute)) + return self._timeout.waitForSet(self, attrs=('localConfig', attribute)) def writeConfig(self): - """Write the current (edited) radioConfig to the device""" - if self.radioConfig is None: - our_exit("Error: No RadioConfig has been read") + """Write the current (edited) localConfig to the device""" + if self.localConfig is None: + our_exit("Error: No localConfig has been read") - p = admin_pb2.AdminMessage() - p.set_radio.CopyFrom(self.radioConfig) + if self.localConfig.device: + p = admin_pb2.AdminMessage() + p.set_config.device.CopyFrom(self.localConfig.device) + self._sendAdmin(p) + logging.debug("Wrote device") - self._sendAdmin(p) - logging.debug("Wrote config") + if self.localConfig.position: + p = admin_pb2.AdminMessage() + p.set_config.position.CopyFrom(self.localConfig.position) + self._sendAdmin(p) + logging.debug("Wrote position") + + if self.localConfig.power: + p = admin_pb2.AdminMessage() + p.set_config.power.CopyFrom(self.localConfig.power) + self._sendAdmin(p) + logging.debug("Wrote power") + + if self.localConfig.wifi: + p = admin_pb2.AdminMessage() + p.set_config.wifi.CopyFrom(self.localConfig.wifi) + self._sendAdmin(p) + logging.debug("Wrote wifi") + + if self.localConfig.display: + p = admin_pb2.AdminMessage() + p.set_config.display.CopyFrom(self.localConfig.display) + self._sendAdmin(p) + logging.debug("Wrote display") + + if self.localConfig.lora: + p = admin_pb2.AdminMessage() + p.set_config.lora.CopyFrom(self.localConfig.lora) + self._sendAdmin(p) + logging.debug("Wrote lora") def writeChannel(self, channelIndex, adminIndex=0): """Write the current (edited) channel to the device""" @@ -214,8 +243,8 @@ class Node: def setURL(self, url): """Set mesh network URL""" - if self.radioConfig is None: - our_exit("Warning: No RadioConfig has been read") + if self.localConfig is None: + our_exit("Warning: No Config has been read") # URLs are of the form https://www.meshtastic.org/d/#{base64_channel_set} # Split on '/#' to find the base64 encoded channel settings