mirror of
https://github.com/meshtastic/python.git
synced 2025-12-30 11:27:53 -05:00
almost working
This commit is contained in:
2
TODO.md
2
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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user