mirror of
https://github.com/meshtastic/python.git
synced 2025-12-27 01:47:50 -05:00
1.2.4
This commit is contained in:
@@ -155,7 +155,7 @@ import base64
|
||||
import platform
|
||||
import socket
|
||||
from . import mesh_pb2, portnums_pb2, apponly_pb2, admin_pb2, environmental_measurement_pb2, remote_hardware_pb2, channel_pb2, radioconfig_pb2, util
|
||||
from .util import fixme, catchAndIgnore
|
||||
from .util import fixme, catchAndIgnore, stripnl
|
||||
from pubsub import pub
|
||||
from dotmap import DotMap
|
||||
from typing import *
|
||||
@@ -275,7 +275,7 @@ class MeshInterface:
|
||||
Returns the sent packet. The id field will be populated in this packet and can be used to track future message acks/naks.
|
||||
"""
|
||||
if getattr(data, "SerializeToString", None):
|
||||
logging.debug(f"Serializing protobuf as data: {data}")
|
||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||
data = data.SerializeToString()
|
||||
|
||||
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
|
||||
@@ -357,6 +357,7 @@ class MeshInterface:
|
||||
meshPacket.id = self._generatePacketId()
|
||||
|
||||
toRadio.packet.CopyFrom(meshPacket)
|
||||
#logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
self._sendToRadio(toRadio)
|
||||
return meshPacket
|
||||
|
||||
@@ -532,7 +533,7 @@ class MeshInterface:
|
||||
logging.warn(
|
||||
f"Not sending packet because protocol use is disabled by noProto")
|
||||
else:
|
||||
logging.debug(f"Sending toRadio: {toRadio}")
|
||||
#logging.debug(f"Sending toRadio: {stripnl(toRadio)}")
|
||||
self._sendToRadioImpl(toRadio)
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
@@ -575,16 +576,21 @@ class MeshInterface:
|
||||
"""A closure to handle the response packet"""
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
logging.debug(f"Received channel {c}")
|
||||
# for stress testing, download all channels
|
||||
# if channelNum >= self.myInfo.max_channels - 1:
|
||||
if c.role == channel_pb2.Channel.Role.DISABLED or channelNum >= self.myInfo.max_channels - 1:
|
||||
# Once we see a response that has NO settings, assume we are at the end of channels and stop fetching
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.myInfo.max_channels - 1:
|
||||
self.channels = self.partialChannels
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self._connected() # Tell everone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(channelNum + 1)
|
||||
self._requestChannel(index + 1)
|
||||
|
||||
return self.sendData(p, self.myInfo.my_node_num,
|
||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||
@@ -600,9 +606,9 @@ class MeshInterface:
|
||||
fromRadio = mesh_pb2.FromRadio()
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
asDict = google.protobuf.json_format.MessageToDict(fromRadio)
|
||||
logging.debug(f"Received: {asDict}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
self.myInfo = fromRadio.my_info
|
||||
logging.debug(f"Received myinfo: {stripnl(fromRadio.my_info)}")
|
||||
|
||||
failmsg = None
|
||||
# Check for app too old
|
||||
@@ -624,6 +630,9 @@ class MeshInterface:
|
||||
self._fixupPosition(node["position"])
|
||||
except:
|
||||
logging.debug("Node without position")
|
||||
|
||||
logging.debug(f"Received nodeinfo: {node}")
|
||||
|
||||
self.nodesByNum[node["num"]] = node
|
||||
if "user" in node: # Some nodes might not have user/ids assigned yet
|
||||
self.nodes[node["user"]["id"]] = node
|
||||
@@ -700,6 +709,14 @@ class MeshInterface:
|
||||
# want the raw protobuf, so we provide it in "raw"
|
||||
asDict["raw"] = meshPacket
|
||||
|
||||
# from might be missing if the nodenum was zero.
|
||||
if not "from" in asDict:
|
||||
asDict["from"] = 0
|
||||
logging.error(f"Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
return
|
||||
if not "to" in asDict:
|
||||
asDict["to"] = 0
|
||||
|
||||
# /add fromId and toId fields based on the node ID
|
||||
asDict["fromId"] = self._nodeNumToId(asDict["from"])
|
||||
asDict["toId"] = self._nodeNumToId(asDict["to"])
|
||||
@@ -758,7 +775,7 @@ class MeshInterface:
|
||||
if handler is not None:
|
||||
handler.callback(asDict)
|
||||
|
||||
logging.debug(f"Publishing topic {topic}")
|
||||
logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
|
||||
catchAndIgnore(f"publishing {topic}", lambda: pub.sendMessage(
|
||||
topic, packet=asDict, interface=self))
|
||||
|
||||
@@ -791,7 +808,7 @@ class BLEInterface(MeshInterface):
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {toRadio}")
|
||||
# logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
self.device.char_write(TORADIO_UUID, b)
|
||||
|
||||
@@ -871,7 +888,7 @@ class StreamInterface(MeshInterface):
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {toRadio}")
|
||||
logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
bufLen = len(b)
|
||||
# We convert into a string, because the TCP code doesn't work with byte arrays
|
||||
@@ -1194,7 +1211,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {toRadio}")
|
||||
# logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
self.device.char_write(TORADIO_UUID, b)
|
||||
|
||||
@@ -1381,7 +1398,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
Returns the sent packet. The id field will be populated in this packet and can be used to track future message acks/naks.
|
||||
"""
|
||||
if getattr(data, "SerializeToString", None):
|
||||
logging.debug(f"Serializing protobuf as data: {data}")
|
||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||
data = data.SerializeToString()
|
||||
|
||||
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
|
||||
@@ -1463,6 +1480,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
meshPacket.id = self._generatePacketId()
|
||||
|
||||
toRadio.packet.CopyFrom(meshPacket)
|
||||
#logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
self._sendToRadio(toRadio)
|
||||
return meshPacket
|
||||
|
||||
@@ -1638,7 +1656,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
logging.warn(
|
||||
f"Not sending packet because protocol use is disabled by noProto")
|
||||
else:
|
||||
logging.debug(f"Sending toRadio: {toRadio}")
|
||||
#logging.debug(f"Sending toRadio: {stripnl(toRadio)}")
|
||||
self._sendToRadioImpl(toRadio)
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
@@ -1681,16 +1699,21 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
"""A closure to handle the response packet"""
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
logging.debug(f"Received channel {c}")
|
||||
# for stress testing, download all channels
|
||||
# if channelNum >= self.myInfo.max_channels - 1:
|
||||
if c.role == channel_pb2.Channel.Role.DISABLED or channelNum >= self.myInfo.max_channels - 1:
|
||||
# Once we see a response that has NO settings, assume we are at the end of channels and stop fetching
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.myInfo.max_channels - 1:
|
||||
self.channels = self.partialChannels
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self._connected() # Tell everone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(channelNum + 1)
|
||||
self._requestChannel(index + 1)
|
||||
|
||||
return self.sendData(p, self.myInfo.my_node_num,
|
||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||
@@ -1706,9 +1729,9 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
fromRadio = mesh_pb2.FromRadio()
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
asDict = google.protobuf.json_format.MessageToDict(fromRadio)
|
||||
logging.debug(f"Received: {asDict}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
self.myInfo = fromRadio.my_info
|
||||
logging.debug(f"Received myinfo: {stripnl(fromRadio.my_info)}")
|
||||
|
||||
failmsg = None
|
||||
# Check for app too old
|
||||
@@ -1730,6 +1753,9 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
self._fixupPosition(node["position"])
|
||||
except:
|
||||
logging.debug("Node without position")
|
||||
|
||||
logging.debug(f"Received nodeinfo: {node}")
|
||||
|
||||
self.nodesByNum[node["num"]] = node
|
||||
if "user" in node: # Some nodes might not have user/ids assigned yet
|
||||
self.nodes[node["user"]["id"]] = node
|
||||
@@ -1806,6 +1832,14 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
# want the raw protobuf, so we provide it in "raw"
|
||||
asDict["raw"] = meshPacket
|
||||
|
||||
# from might be missing if the nodenum was zero.
|
||||
if not "from" in asDict:
|
||||
asDict["from"] = 0
|
||||
logging.error(f"Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
return
|
||||
if not "to" in asDict:
|
||||
asDict["to"] = 0
|
||||
|
||||
# /add fromId and toId fields based on the node ID
|
||||
asDict["fromId"] = self._nodeNumToId(asDict["from"])
|
||||
asDict["toId"] = self._nodeNumToId(asDict["to"])
|
||||
@@ -1864,7 +1898,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
if handler is not None:
|
||||
handler.callback(asDict)
|
||||
|
||||
logging.debug(f"Publishing topic {topic}")
|
||||
logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
|
||||
catchAndIgnore(f"publishing {topic}", lambda: pub.sendMessage(
|
||||
topic, packet=asDict, interface=self))</code></pre>
|
||||
</details>
|
||||
@@ -1996,7 +2030,7 @@ onResponse – A closure of the form funct(packet), that will be called when
|
||||
Returns the sent packet. The id field will be populated in this packet and can be used to track future message acks/naks.
|
||||
"""
|
||||
if getattr(data, "SerializeToString", None):
|
||||
logging.debug(f"Serializing protobuf as data: {data}")
|
||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||
data = data.SerializeToString()
|
||||
|
||||
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
|
||||
@@ -2429,7 +2463,7 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {toRadio}")
|
||||
logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
bufLen = len(b)
|
||||
# We convert into a string, because the TCP code doesn't work with byte arrays
|
||||
|
||||
@@ -34,6 +34,11 @@ import serial.tools.list_ports
|
||||
blacklistVids = dict.fromkeys([0x1366])
|
||||
|
||||
|
||||
def stripnl(s):
|
||||
"""remove newlines from a string"""
|
||||
return str(s).replace("\n", " ")
|
||||
|
||||
|
||||
def fixme(message):
|
||||
raise Exception(f"FIXME: {message}")
|
||||
|
||||
@@ -127,6 +132,20 @@ class dotdict(dict):
|
||||
raise Exception(f"FIXME: {message}")</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.util.stripnl"><code class="name flex">
|
||||
<span>def <span class="ident">stripnl</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>remove newlines from a string</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def stripnl(s):
|
||||
"""remove newlines from a string"""
|
||||
return str(s).replace("\n", " ")</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
@@ -172,6 +191,7 @@ class dotdict(dict):
|
||||
<li><code><a title="meshtastic.util.catchAndIgnore" href="#meshtastic.util.catchAndIgnore">catchAndIgnore</a></code></li>
|
||||
<li><code><a title="meshtastic.util.findPorts" href="#meshtastic.util.findPorts">findPorts</a></code></li>
|
||||
<li><code><a title="meshtastic.util.fixme" href="#meshtastic.util.fixme">fixme</a></code></li>
|
||||
<li><code><a title="meshtastic.util.stripnl" href="#meshtastic.util.stripnl">stripnl</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
|
||||
2
setup.py
2
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.3",
|
||||
version="1.2.4",
|
||||
description="Python API & client shell for talking to Meshtastic devices",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
|
||||
Reference in New Issue
Block a user