diff --git a/docs/meshtastic/index.html b/docs/meshtastic/index.html
index 485594d..d2c4151 100644
--- a/docs/meshtastic/index.html
+++ b/docs/meshtastic/index.html
@@ -218,7 +218,7 @@ class MeshInterface:
self.noProto = noProto
self.myInfo = None # We don't have device info yet
self.responseHandlers = {} # A map from request ID to the handler
- self.failure = None # If we've encountered a fatal exception it will be kept here
+ self.failure = None # If we've encountered a fatal exception it will be kept here
random.seed() # FIXME, we should not clobber the random seedval here, instead tell user they must call it
self.currentPacketId = random.randint(0, 0xffffffff)
self._startConfig()
@@ -377,10 +377,21 @@ class MeshInterface:
p.set_radio.CopyFrom(self.radioConfig)
self.sendData(p, self.myInfo.my_node_num,
- portNum=portnums_pb2.PortNum.ADMIN_APP,
- wantAck=True)
+ portNum=portnums_pb2.PortNum.ADMIN_APP,
+ wantAck=True)
logging.debug("Wrote config")
+ def writeChannel(self, channelIndex):
+ """Write the current (edited) channel to the device"""
+
+ p = admin_pb2.AdminMessage()
+ p.set_channel.CopyFrom(self.channels[channelIndex])
+
+ self.sendData(p, self.myInfo.my_node_num,
+ portNum=portnums_pb2.PortNum.ADMIN_APP,
+ wantAck=True)
+ logging.debug("Wrote channel {channelIndex}")
+
def getMyNodeInfo(self):
if self.myInfo is None:
return None
@@ -460,8 +471,16 @@ class MeshInterface:
decodedURL = base64.urlsafe_b64decode(splitURL[-1])
channelSet = apponly_pb2.ChannelSet()
channelSet.ParseFromString(decodedURL)
- fixme("set self.channels, see https://developers.google.com/protocol-buffers/docs/reference/python-generated?csw=1#repeated-fields")
- self._writeChannels()
+
+ 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
+ self.writeChannel(ch.index)
+ i = i + 1
def _waitConnected(self):
"""Block until the initial node db download is complete, or timeout
@@ -596,7 +615,7 @@ class MeshInterface:
if failmsg:
self.failure = Exception(failmsg)
- self.isConnected.set() # let waitConnected return this exception
+ self.isConnected.set() # let waitConnected return this exception
self.close()
elif fromRadio.HasField("node_info"):
@@ -1221,6 +1240,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
setOwner
setURL
waitForConfig
+writeChannel
writeConfig
@@ -1304,7 +1324,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
self.noProto = noProto
self.myInfo = None # We don't have device info yet
self.responseHandlers = {} # A map from request ID to the handler
- self.failure = None # If we've encountered a fatal exception it will be kept here
+ self.failure = None # If we've encountered a fatal exception it will be kept here
random.seed() # FIXME, we should not clobber the random seedval here, instead tell user they must call it
self.currentPacketId = random.randint(0, 0xffffffff)
self._startConfig()
@@ -1463,10 +1483,21 @@ noProto – If True, don't try to run our protocol on the link - just be a d
p.set_radio.CopyFrom(self.radioConfig)
self.sendData(p, self.myInfo.my_node_num,
- portNum=portnums_pb2.PortNum.ADMIN_APP,
- wantAck=True)
+ portNum=portnums_pb2.PortNum.ADMIN_APP,
+ wantAck=True)
logging.debug("Wrote config")
+ def writeChannel(self, channelIndex):
+ """Write the current (edited) channel to the device"""
+
+ p = admin_pb2.AdminMessage()
+ p.set_channel.CopyFrom(self.channels[channelIndex])
+
+ self.sendData(p, self.myInfo.my_node_num,
+ portNum=portnums_pb2.PortNum.ADMIN_APP,
+ wantAck=True)
+ logging.debug("Wrote channel {channelIndex}")
+
def getMyNodeInfo(self):
if self.myInfo is None:
return None
@@ -1546,8 +1577,16 @@ noProto – If True, don't try to run our protocol on the link - just be a d
decodedURL = base64.urlsafe_b64decode(splitURL[-1])
channelSet = apponly_pb2.ChannelSet()
channelSet.ParseFromString(decodedURL)
- fixme("set self.channels, see https://developers.google.com/protocol-buffers/docs/reference/python-generated?csw=1#repeated-fields")
- self._writeChannels()
+
+ 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
+ self.writeChannel(ch.index)
+ i = i + 1
def _waitConnected(self):
"""Block until the initial node db download is complete, or timeout
@@ -1682,7 +1721,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
if failmsg:
self.failure = Exception(failmsg)
- self.isConnected.set() # let waitConnected return this exception
+ self.isConnected.set() # let waitConnected return this exception
self.close()
elif fromRadio.HasField("node_info"):
@@ -2121,8 +2160,16 @@ wantResponse – True if you want the service on the other side to send an a
decodedURL = base64.urlsafe_b64decode(splitURL[-1])
channelSet = apponly_pb2.ChannelSet()
channelSet.ParseFromString(decodedURL)
- fixme("set self.channels, see https://developers.google.com/protocol-buffers/docs/reference/python-generated?csw=1#repeated-fields")
- self._writeChannels()
+
+ 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
+ self.writeChannel(ch.index)
+ i = i + 1
@@ -2143,6 +2190,27 @@ wantResponse – True if you want the service on the other side to send an a
return False
+
+def writeChannel(self, channelIndex)
+
+
+Write the current (edited) channel to the device
+
+
+Expand source code
+
+def writeChannel(self, channelIndex):
+ """Write the current (edited) channel to the device"""
+
+ p = admin_pb2.AdminMessage()
+ p.set_channel.CopyFrom(self.channels[channelIndex])
+
+ self.sendData(p, self.myInfo.my_node_num,
+ portNum=portnums_pb2.PortNum.ADMIN_APP,
+ wantAck=True)
+ logging.debug("Wrote channel {channelIndex}")
+
+
def writeConfig(self)
@@ -2161,8 +2229,8 @@ wantResponse – True if you want the service on the other side to send an a
p.set_radio.CopyFrom(self.radioConfig)
self.sendData(p, self.myInfo.my_node_num,
- portNum=portnums_pb2.PortNum.ADMIN_APP,
- wantAck=True)
+ portNum=portnums_pb2.PortNum.ADMIN_APP,
+ wantAck=True)
logging.debug("Wrote config")
@@ -2270,6 +2338,7 @@ debugOut {stream} – If a stream is provided, any debug serial output from
setOwner
setURL
waitForConfig
+writeChannel
writeConfig
@@ -2506,6 +2575,7 @@ start the reading thread later.
setOwner
setURL
waitForConfig
+writeChannel
writeConfig
@@ -2584,6 +2654,7 @@ hostname {string} – Hostname/IP address of the device to connect tosetOwner
setURL
waitForConfig
+writeChannel
writeConfig
@@ -2655,6 +2726,7 @@ hostname {string} – Hostname/IP address of the device to connect tosetOwner
setURL
waitForConfig
+writeChannel
writeConfig
diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py
index 4a29f13..bc27ca5 100644
--- a/meshtastic/__main__.py
+++ b/meshtastic/__main__.py
@@ -34,14 +34,16 @@ def onReceive(packet, interface):
logging.debug(f"Received: {packet}")
try:
+ d = packet.get('decoded')
+
# Exit once we receive a reply
- if args.sendtext and packet["to"] == interface.myInfo.my_node_num:
+ if args.sendtext and packet["to"] == interface.myInfo.my_node_num and d["portnum"] == portnums_pb2.PortNum.TEXT_MESSAGE_APP:
interface.close() # after running command then exit
# Reply to every received message with some stats
if args.reply:
- if packet['decoded']['data'] is not None:
- msg = packet['decoded']['data']['text']
+ msg = d.get('text')
+ if msg:
#shortName = packet['decoded']['data']['shortName']
rxSnr = packet['rxSnr']
hopLimit = packet['hopLimit']
diff --git a/setup.py b/setup.py
index 3524f46..44e9f98 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@ with open("README.md", "r") as fh:
# This call to setup() does all the work
setup(
name="meshtastic",
- version="1.2.2",
+ version="1.2.3",
description="Python API & client shell for talking to Meshtastic devices",
long_description=long_description,
long_description_content_type="text/markdown",