diff --git a/docs/meshtastic/index.html b/docs/meshtastic/index.html index fc29746..0cb6265 100644 --- a/docs/meshtastic/index.html +++ b/docs/meshtastic/index.html @@ -206,7 +206,7 @@ class MeshInterface: meshPacket.decoded.position.altitude = int(altitude) if timeSec == 0: - timeSec = time.time() # returns unix timestamp in seconds + timeSec = time.time() # returns unix timestamp in seconds meshPacket.decoded.position.time = int(timeSec) meshPacket.decoded.want_response = wantResponse @@ -377,6 +377,12 @@ class MeshInterface: if meshPacket.decoded.HasField("data"): topic = "meshtastic.receive.data" + + # OPAQUE is the default protobuf typ value, and therefore if not set it will not be populated at all + # to make API usage easier, set it to prevent confusion + if not "typ" in asDict["decoded"]["data"]: + asDict["decoded"]["data"]["typ"] = "OPAQUE" + # For text messages, we go ahead and decode the text to ascii for our users if asDict["decoded"]["data"]["typ"] == "CLEAR_TEXT": asDict["decoded"]["data"]["text"] = meshPacket.decoded.data.payload.decode( @@ -432,7 +438,7 @@ class BLEInterface(MeshInterface): class StreamInterface(MeshInterface): """Interface class for meshtastic devices over a stream link (serial, TCP, etc)""" - def __init__(self, devPath=None, debugOut=None, noProto=False): + def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True): """Constructor, opens a connection to a specified serial port, or if unspecified try to find one Meshtastic device by probing @@ -463,14 +469,24 @@ class StreamInterface(MeshInterface): devPath, 921600, exclusive=True, timeout=0.5) self._rxThread = threading.Thread(target=self.__reader, args=()) + MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto) + + # Start the reader thread after superclass constructor completes init + if connectNow: + self.connect() + + def connect(self): + """Connect to our radio + + Normally this is called automatically by the constructor, but if you passed in connectNow=False you can manually + start the reading thread later. + """ + # Send some bogus UART characters to force a sleeping device to wake self.stream.write(bytes([START1, START1, START1, START1])) self.stream.flush() time.sleep(0.1) # wait 100ms to give device time to start running - MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto) - - # Start the reader thread after superclass constructor completes init self._rxThread.start() def _sendToRadio(self, toRadio): @@ -730,7 +746,7 @@ debugOut

meshPacket.decoded.position.altitude = int(altitude) if timeSec == 0: - timeSec = time.time() # returns unix timestamp in seconds + timeSec = time.time() # returns unix timestamp in seconds meshPacket.decoded.position.time = int(timeSec) meshPacket.decoded.want_response = wantResponse @@ -901,6 +917,12 @@ debugOut

if meshPacket.decoded.HasField("data"): topic = "meshtastic.receive.data" + + # OPAQUE is the default protobuf typ value, and therefore if not set it will not be populated at all + # to make API usage easier, set it to prevent confusion + if not "typ" in asDict["decoded"]["data"]: + asDict["decoded"]["data"]["typ"] = "OPAQUE" + # For text messages, we go ahead and decode the text to ascii for our users if asDict["decoded"]["data"]["typ"] == "CLEAR_TEXT": asDict["decoded"]["data"]["text"] = meshPacket.decoded.data.payload.decode( @@ -994,7 +1016,7 @@ the local position.

meshPacket.decoded.position.altitude = int(altitude) if timeSec == 0: - timeSec = time.time() # returns unix timestamp in seconds + timeSec = time.time() # returns unix timestamp in seconds meshPacket.decoded.position.time = int(timeSec) meshPacket.decoded.want_response = wantResponse @@ -1050,7 +1072,7 @@ destinationId {nodeId or nodeNum} – where to send this message (default: {
class StreamInterface -(devPath=None, debugOut=None, noProto=False) +(devPath=None, debugOut=None, noProto=False, connectNow=True)

Interface class for meshtastic devices over a stream link (serial, TCP, etc)

@@ -1073,7 +1095,7 @@ debugOut {stream} – If a stream is provided, any debug serial output from
class StreamInterface(MeshInterface):
     """Interface class for meshtastic devices over a stream link (serial, TCP, etc)"""
 
-    def __init__(self, devPath=None, debugOut=None, noProto=False):
+    def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
         """Constructor, opens a connection to a specified serial port, or if unspecified try to
         find one Meshtastic device by probing
 
@@ -1104,14 +1126,24 @@ debugOut {stream} – If a stream is provided, any debug serial output from
             devPath, 921600, exclusive=True, timeout=0.5)
         self._rxThread = threading.Thread(target=self.__reader, args=())
 
+        MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
+
+        # Start the reader thread after superclass constructor completes init
+        if connectNow:
+            self.connect()
+
+    def connect(self):
+        """Connect to our radio
+
+        Normally this is called automatically by the constructor, but if you passed in connectNow=False you can manually
+        start the reading thread later.
+        """
+
         # Send some bogus UART characters to force a sleeping device to wake
         self.stream.write(bytes([START1, START1, START1, START1]))
         self.stream.flush()
         time.sleep(0.1)  # wait 100ms to give device time to start running
 
-        MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
-
-        # Start the reader thread after superclass constructor completes init
         self._rxThread.start()
 
     def _sendToRadio(self, toRadio):
@@ -1205,6 +1237,32 @@ debugOut {stream} – If a stream is provided, any debug serial output from
         self._rxThread.join()  # wait for it to exit
+
+def connect(self) +
+
+

Connect to our radio

+

Normally this is called automatically by the constructor, but if you passed in connectNow=False you can manually +start the reading thread later.

+
+ +Expand source code + +
def connect(self):
+    """Connect to our radio
+
+    Normally this is called automatically by the constructor, but if you passed in connectNow=False you can manually
+    start the reading thread later.
+    """
+
+    # Send some bogus UART characters to force a sleeping device to wake
+    self.stream.write(bytes([START1, START1, START1, START1]))
+    self.stream.flush()
+    time.sleep(0.1)  # wait 100ms to give device time to start running
+
+    self._rxThread.start()
+
+

Inherited members

diff --git a/docs/meshtastic/test.html b/docs/meshtastic/test.html index e146550..b1cd793 100644 --- a/docs/meshtastic/test.html +++ b/docs/meshtastic/test.html @@ -65,7 +65,7 @@ def subscribe(): pub.subscribe(onNode, "meshtastic.node") -def testSend(fromInterface, toInterface, isBroadcast=False): +def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False): """ Sends one test packet between two nodes and then returns success or failure @@ -86,7 +86,12 @@ def testSend(fromInterface, toInterface, isBroadcast=False): toNode = toInterface.myInfo.my_node_num logging.info(f"Sending test packet from {fromNode} to {toNode}") - fromInterface.sendText(f"Test {testNumber}", toNode, wantAck=True) + wantAck = True + if not asBinary: + fromInterface.sendText(f"Test {testNumber}", toNode, wantAck=wantAck) + else: + fromInterface.sendData((f"Binary {testNumber}").encode( + "utf-8"), toNode, wantAck=wantAck) time.sleep(45) return (len(receivedPackets) >= 1) @@ -99,7 +104,8 @@ def testThread(numTests=50): global testNumber testNumber = testNumber + 1 isBroadcast = True - success = testSend(interfaces[0], interfaces[1], isBroadcast) + success = testSend( + interfaces[0], interfaces[1], isBroadcast, asBinary=(i % 2 == 0)) if not success: numFail = numFail + 1 logging.error( @@ -121,6 +127,7 @@ def onConnection(topic=pub.AUTO_TOPIC): print(f"Connection changed: {topic.getName()}") global testsRunning + global interfaces if (all(iface.isConnected for iface in interfaces) and not testsRunning): testsRunning = True t = threading.Thread(target=testThread, args=()) @@ -148,7 +155,10 @@ def testAll(): pub.subscribe(onReceive, "meshtastic.receive") global interfaces interfaces = list(map(lambda port: StreamInterface( - port, debugOut=openDebugLog(port)), ports)) + port, debugOut=openDebugLog(port), connectNow=False), ports)) + for i in interfaces: + i.connect() + logging.info("Ports opened, waiting for device to complete connection") @@ -180,6 +190,7 @@ def testAll(): print(f"Connection changed: {topic.getName()}") global testsRunning + global interfaces if (all(iface.isConnected for iface in interfaces) and not testsRunning): testsRunning = True t = threading.Thread(target=testThread, args=()) @@ -278,12 +289,15 @@ def testAll(): pub.subscribe(onReceive, "meshtastic.receive") global interfaces interfaces = list(map(lambda port: StreamInterface( - port, debugOut=openDebugLog(port)), ports)) + port, debugOut=openDebugLog(port), connectNow=False), ports)) + for i in interfaces: + i.connect() + logging.info("Ports opened, waiting for device to complete connection")
-def testSend(fromInterface, toInterface, isBroadcast=False) +def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False)

Sends one test packet between two nodes and then returns success or failure

@@ -299,7 +313,7 @@ toInterface {[type]} – [description]

Expand source code -
def testSend(fromInterface, toInterface, isBroadcast=False):
+
def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False):
     """
     Sends one test packet between two nodes and then returns success or failure
 
@@ -320,7 +334,12 @@ toInterface {[type]} – [description]

toNode = toInterface.myInfo.my_node_num logging.info(f"Sending test packet from {fromNode} to {toNode}") - fromInterface.sendText(f"Test {testNumber}", toNode, wantAck=True) + wantAck = True + if not asBinary: + fromInterface.sendText(f"Test {testNumber}", toNode, wantAck=wantAck) + else: + fromInterface.sendData((f"Binary {testNumber}").encode( + "utf-8"), toNode, wantAck=wantAck) time.sleep(45) return (len(receivedPackets) >= 1)
@@ -342,7 +361,8 @@ toInterface {[type]} – [description]

global testNumber testNumber = testNumber + 1 isBroadcast = True - success = testSend(interfaces[0], interfaces[1], isBroadcast) + success = testSend( + interfaces[0], interfaces[1], isBroadcast, asBinary=(i % 2 == 0)) if not success: numFail = numFail + 1 logging.error( diff --git a/setup.py b/setup.py index 7b5f696..84f43e5 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ with open("README.md", "r") as fh: # This call to setup() does all the work setup( name="meshtastic", - version="0.9.1", + version="0.9.2", description="Python API & client shell for talking to Meshtastic devices", long_description=long_description, long_description_content_type="text/markdown",