mirror of
https://github.com/meshtastic/python.git
synced 2026-02-16 02:41:15 -05:00
1.2.32
This commit is contained in:
@@ -231,12 +231,15 @@ class MeshInterface:
|
||||
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._timeout = Timeout()
|
||||
self.heartbeatTimer = None
|
||||
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()
|
||||
|
||||
def close(self):
|
||||
"""Shutdown this interface"""
|
||||
if self.heartbeatTimer:
|
||||
self.heartbeatTimer.cancel()
|
||||
|
||||
self._sendDisconnect()
|
||||
|
||||
def __enter__(self):
|
||||
@@ -521,6 +524,22 @@ class MeshInterface:
|
||||
publishingThread.queueWork(lambda: pub.sendMessage(
|
||||
"meshtastic.connection.lost", interface=self))
|
||||
|
||||
def _startHeartbeat(self):
|
||||
"""We need to send a heartbeat message to the device every X seconds"""
|
||||
def callback():
|
||||
self.heartbeatTimer = None
|
||||
prefs = self.localNode.radioConfig.preferences
|
||||
i = prefs.phone_timeout_secs / 2
|
||||
logging.debug(f"Sending heartbeat, interval {i}")
|
||||
if i != 0:
|
||||
self.heartbeatTimer = threading.Timer(i, callback)
|
||||
self.heartbeatTimer.start()
|
||||
p = mesh_pb2.ToRadio()
|
||||
self._sendToRadio(p)
|
||||
|
||||
callback() # run our periodic callback now, it will make another timer if necessary
|
||||
|
||||
|
||||
def _connected(self):
|
||||
"""Called by this class to tell clients we are now fully connected to a node
|
||||
"""
|
||||
@@ -529,6 +548,7 @@ class MeshInterface:
|
||||
# for the local interface
|
||||
if not self.isConnected.is_set():
|
||||
self.isConnected.set()
|
||||
self._startHeartbeat()
|
||||
publishingThread.queueWork(lambda: pub.sendMessage(
|
||||
"meshtastic.connection.established", interface=self))
|
||||
|
||||
@@ -576,7 +596,7 @@ class MeshInterface:
|
||||
fromRadio = mesh_pb2.FromRadio()
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
asDict = google.protobuf.json_format.MessageToDict(fromRadio)
|
||||
# logging.debug(f"Received from radio: {fromRadio}")
|
||||
#logging.debug(f"Received from radio: {fromRadio}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
self.myInfo = fromRadio.my_info
|
||||
self.localNode.nodeNum = self.myInfo.my_node_num
|
||||
@@ -788,7 +808,7 @@ class BLEInterface(MeshInterface):
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
# logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
#logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
self.device.char_write(TORADIO_UUID, b)
|
||||
|
||||
@@ -844,11 +864,16 @@ class StreamInterface(MeshInterface):
|
||||
start the reading thread later.
|
||||
"""
|
||||
|
||||
# Send some bogus UART characters to force a sleeping device to wake
|
||||
self._writeBytes(bytes([START1, START1, START1, START1]))
|
||||
# Send some bogus UART characters to force a sleeping device to wake, and if the reading statemachine was parsing a bad packet make sure
|
||||
# we write enought start bytes to force it to resync
|
||||
p = bytearray([START1] * 32)
|
||||
self._writeBytes(p)
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
self._rxThread.start()
|
||||
|
||||
self._startConfig()
|
||||
|
||||
if not self.noProto: # Wait for the db download if using the protocol
|
||||
self._waitConnected()
|
||||
|
||||
@@ -918,15 +943,15 @@ class StreamInterface(MeshInterface):
|
||||
elif ptr == 1: # looking for START2
|
||||
if c != START2:
|
||||
self._rxBuf = empty # failed to find start2
|
||||
elif ptr >= HEADER_LEN: # we've at least got a header
|
||||
elif ptr >= HEADER_LEN - 1: # we've at least got a header
|
||||
# big endian length follos header
|
||||
packetlen = (self._rxBuf[2] << 8) + self._rxBuf[3]
|
||||
|
||||
if ptr == HEADER_LEN: # we _just_ finished reading the header, validate length
|
||||
if ptr == HEADER_LEN - 1: # we _just_ finished reading the header, validate length
|
||||
if packetlen > MAX_TO_FROM_RADIO_SIZE:
|
||||
self._rxBuf = empty # length ws out out bounds, restart
|
||||
|
||||
if len(self._rxBuf) != 0 and ptr + 1 == packetlen + HEADER_LEN:
|
||||
if len(self._rxBuf) != 0 and ptr + 1 >= packetlen + HEADER_LEN:
|
||||
try:
|
||||
self._handleFromRadio(self._rxBuf[HEADER_LEN:])
|
||||
except Exception as ex:
|
||||
@@ -1216,7 +1241,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: {stripnl(toRadio)}")
|
||||
#logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
self.device.char_write(TORADIO_UUID, b)
|
||||
|
||||
@@ -1333,12 +1358,15 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
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._timeout = Timeout()
|
||||
self.heartbeatTimer = None
|
||||
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()
|
||||
|
||||
def close(self):
|
||||
"""Shutdown this interface"""
|
||||
if self.heartbeatTimer:
|
||||
self.heartbeatTimer.cancel()
|
||||
|
||||
self._sendDisconnect()
|
||||
|
||||
def __enter__(self):
|
||||
@@ -1623,6 +1651,22 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
publishingThread.queueWork(lambda: pub.sendMessage(
|
||||
"meshtastic.connection.lost", interface=self))
|
||||
|
||||
def _startHeartbeat(self):
|
||||
"""We need to send a heartbeat message to the device every X seconds"""
|
||||
def callback():
|
||||
self.heartbeatTimer = None
|
||||
prefs = self.localNode.radioConfig.preferences
|
||||
i = prefs.phone_timeout_secs / 2
|
||||
logging.debug(f"Sending heartbeat, interval {i}")
|
||||
if i != 0:
|
||||
self.heartbeatTimer = threading.Timer(i, callback)
|
||||
self.heartbeatTimer.start()
|
||||
p = mesh_pb2.ToRadio()
|
||||
self._sendToRadio(p)
|
||||
|
||||
callback() # run our periodic callback now, it will make another timer if necessary
|
||||
|
||||
|
||||
def _connected(self):
|
||||
"""Called by this class to tell clients we are now fully connected to a node
|
||||
"""
|
||||
@@ -1631,6 +1675,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
# for the local interface
|
||||
if not self.isConnected.is_set():
|
||||
self.isConnected.set()
|
||||
self._startHeartbeat()
|
||||
publishingThread.queueWork(lambda: pub.sendMessage(
|
||||
"meshtastic.connection.established", interface=self))
|
||||
|
||||
@@ -1678,7 +1723,7 @@ 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 from radio: {fromRadio}")
|
||||
#logging.debug(f"Received from radio: {fromRadio}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
self.myInfo = fromRadio.my_info
|
||||
self.localNode.nodeNum = self.myInfo.my_node_num
|
||||
@@ -1879,6 +1924,9 @@ noProto – If True, don't try to run our protocol on the link - just be a d
|
||||
</summary>
|
||||
<pre><code class="python">def close(self):
|
||||
"""Shutdown this interface"""
|
||||
if self.heartbeatTimer:
|
||||
self.heartbeatTimer.cancel()
|
||||
|
||||
self._sendDisconnect()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
@@ -2377,11 +2425,16 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
start the reading thread later.
|
||||
"""
|
||||
|
||||
# Send some bogus UART characters to force a sleeping device to wake
|
||||
self._writeBytes(bytes([START1, START1, START1, START1]))
|
||||
# Send some bogus UART characters to force a sleeping device to wake, and if the reading statemachine was parsing a bad packet make sure
|
||||
# we write enought start bytes to force it to resync
|
||||
p = bytearray([START1] * 32)
|
||||
self._writeBytes(p)
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
self._rxThread.start()
|
||||
|
||||
self._startConfig()
|
||||
|
||||
if not self.noProto: # Wait for the db download if using the protocol
|
||||
self._waitConnected()
|
||||
|
||||
@@ -2451,15 +2504,15 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
elif ptr == 1: # looking for START2
|
||||
if c != START2:
|
||||
self._rxBuf = empty # failed to find start2
|
||||
elif ptr >= HEADER_LEN: # we've at least got a header
|
||||
elif ptr >= HEADER_LEN - 1: # we've at least got a header
|
||||
# big endian length follos header
|
||||
packetlen = (self._rxBuf[2] << 8) + self._rxBuf[3]
|
||||
|
||||
if ptr == HEADER_LEN: # we _just_ finished reading the header, validate length
|
||||
if ptr == HEADER_LEN - 1: # we _just_ finished reading the header, validate length
|
||||
if packetlen > MAX_TO_FROM_RADIO_SIZE:
|
||||
self._rxBuf = empty # length ws out out bounds, restart
|
||||
|
||||
if len(self._rxBuf) != 0 and ptr + 1 == packetlen + HEADER_LEN:
|
||||
if len(self._rxBuf) != 0 and ptr + 1 >= packetlen + HEADER_LEN:
|
||||
try:
|
||||
self._handleFromRadio(self._rxBuf[HEADER_LEN:])
|
||||
except Exception as ex:
|
||||
@@ -2533,11 +2586,16 @@ start the reading thread later.</p></div>
|
||||
start the reading thread later.
|
||||
"""
|
||||
|
||||
# Send some bogus UART characters to force a sleeping device to wake
|
||||
self._writeBytes(bytes([START1, START1, START1, START1]))
|
||||
# Send some bogus UART characters to force a sleeping device to wake, and if the reading statemachine was parsing a bad packet make sure
|
||||
# we write enought start bytes to force it to resync
|
||||
p = bytearray([START1] * 32)
|
||||
self._writeBytes(p)
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
self._rxThread.start()
|
||||
|
||||
self._startConfig()
|
||||
|
||||
if not self.noProto: # Wait for the db download if using the protocol
|
||||
self._waitConnected()</code></pre>
|
||||
</details>
|
||||
|
||||
@@ -124,11 +124,11 @@ def runTests(numTests=50, wantAck=False, maxFailures=0):
|
||||
if not success:
|
||||
numFail = numFail + 1
|
||||
logging.error(
|
||||
f"Test failed, expected packet not received ({numFail} failures so far)")
|
||||
f"Test {testNumber} failed, expected packet not received ({numFail} failures so far)")
|
||||
else:
|
||||
numSuccess = numSuccess + 1
|
||||
logging.info(
|
||||
f"Test succeeded {numSuccess} successes {numFail} failures so far")
|
||||
f"Test {testNumber} succeeded {numSuccess} successes {numFail} failures so far")
|
||||
|
||||
# if numFail >= 3:
|
||||
# for i in interfaces:
|
||||
@@ -314,11 +314,11 @@ def testSimulator():
|
||||
if not success:
|
||||
numFail = numFail + 1
|
||||
logging.error(
|
||||
f"Test failed, expected packet not received ({numFail} failures so far)")
|
||||
f"Test {testNumber} failed, expected packet not received ({numFail} failures so far)")
|
||||
else:
|
||||
numSuccess = numSuccess + 1
|
||||
logging.info(
|
||||
f"Test succeeded {numSuccess} successes {numFail} failures so far")
|
||||
f"Test {testNumber} succeeded {numSuccess} successes {numFail} failures so far")
|
||||
|
||||
# if numFail >= 3:
|
||||
# for i in interfaces:
|
||||
|
||||
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.31",
|
||||
version="1.2.32",
|
||||
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