mirror of
https://github.com/meshtastic/python.git
synced 2026-01-02 04:47:54 -05:00
1.0.13
This commit is contained in:
@@ -74,7 +74,7 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
pub.subscribe(onConnection, "meshtastic.connection.established")
|
||||
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
|
||||
interface = meshtastic.StreamInterface()
|
||||
interface = meshtastic.SerialInterface()
|
||||
|
||||
</code></pre>
|
||||
<details class="source">
|
||||
@@ -130,12 +130,13 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
pub.subscribe(onConnection, "meshtastic.connection.established")
|
||||
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
|
||||
interface = meshtastic.StreamInterface()
|
||||
interface = meshtastic.SerialInterface()
|
||||
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
import socket
|
||||
import pygatt
|
||||
import google.protobuf.json_format
|
||||
import serial
|
||||
@@ -358,10 +359,12 @@ class MeshInterface:
|
||||
elif fromRadio.HasField("packet"):
|
||||
self._handlePacketFromRadio(fromRadio.packet)
|
||||
elif fromRadio.rebooted:
|
||||
self._disconnected()
|
||||
# Tell clients the device went away. Careful not to call the overridden subclass version that closes the serial port
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
self._startConfig() # redownload the node db etc...
|
||||
else:
|
||||
logging.warn("Unexpected FromRadio payload")
|
||||
logging.debug("Unexpected FromRadio payload")
|
||||
|
||||
def _fixupPosition(self, position):
|
||||
"""Convert integer lat/lon into floats
|
||||
@@ -500,9 +503,8 @@ 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, connectNow=True):
|
||||
"""Constructor, opens a connection to a specified serial port, or if unspecified try to
|
||||
find one Meshtastic device by probing
|
||||
def __init__(self, debugOut=None, noProto=False, connectNow=True):
|
||||
"""Constructor, opens a connection to self.stream
|
||||
|
||||
Keyword Arguments:
|
||||
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
@@ -513,35 +515,12 @@ class StreamInterface(MeshInterface):
|
||||
Exception: [description]
|
||||
"""
|
||||
|
||||
if devPath is None:
|
||||
ports = util.findPorts()
|
||||
if len(ports) == 0:
|
||||
raise Exception("No Meshtastic devices detected")
|
||||
elif len(ports) > 1:
|
||||
raise Exception(
|
||||
f"Multiple ports detected, you must specify a device, such as {ports[0].device}")
|
||||
else:
|
||||
devPath = ports[0]
|
||||
|
||||
logging.debug(f"Connecting to {devPath}")
|
||||
self.devPath = devPath
|
||||
if not hasattr(self, 'stream'):
|
||||
raise Exception(
|
||||
"StreamInterface is now abstract (to update existing code create SerialInterface instead)")
|
||||
self._rxBuf = bytes() # empty
|
||||
self._wantExit = False
|
||||
|
||||
# Note: we provide None for port here, because we will be opening it later
|
||||
self.stream = serial.Serial(
|
||||
None, 921600, exclusive=True, timeout=0.5)
|
||||
|
||||
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
|
||||
self.stream.port = devPath
|
||||
# OS-X seems to have a bug in its serial driver. It ignores that we asked for no RTSCTS
|
||||
# control and will always drive RTS either high or low (rather than letting the CP102 leave
|
||||
# it as an open-collector floating pin). Since it is going to drive it anyways we want to make
|
||||
# sure it is driven low, so that the TBEAM won't reset
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = False
|
||||
self.stream.open()
|
||||
|
||||
self._rxThread = threading.Thread(target=self.__reader, args=())
|
||||
|
||||
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
|
||||
@@ -558,21 +537,36 @@ class StreamInterface(MeshInterface):
|
||||
"""
|
||||
|
||||
# Send some bogus UART characters to force a sleeping device to wake
|
||||
self.stream.write(bytes([START1, START1, START1, START1]))
|
||||
self.stream.flush()
|
||||
self._writeBytes(bytes([START1, START1, START1, START1]))
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
self._rxThread.start()
|
||||
|
||||
def _disconnected(self):
|
||||
"""We override the superclass implementation to close our port"""
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
logging.debug("Closing our port")
|
||||
if not self.stream is None:
|
||||
self.stream.close()
|
||||
|
||||
def _writeBytes(self, b):
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
self.stream.write(b)
|
||||
self.stream.flush()
|
||||
|
||||
def _readBytes(self, len):
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.stream.read(len)
|
||||
|
||||
def _sendToRadio(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {toRadio}")
|
||||
b = toRadio.SerializeToString()
|
||||
bufLen = len(b)
|
||||
# We convert into a string, because the TCP code doesn't work with byte arrays
|
||||
header = bytes([START1, START2, (bufLen >> 8) & 0xff, bufLen & 0xff])
|
||||
self.stream.write(header)
|
||||
self.stream.write(b)
|
||||
self.stream.flush()
|
||||
self._writeBytes(header + b)
|
||||
|
||||
def close(self):
|
||||
"""Close a connection to the device"""
|
||||
@@ -588,7 +582,7 @@ class StreamInterface(MeshInterface):
|
||||
|
||||
try:
|
||||
while not self._wantExit:
|
||||
b = self.stream.read(1)
|
||||
b = self._readBytes(1)
|
||||
if len(b) > 0:
|
||||
# logging.debug(f"read returned {b}")
|
||||
c = b[0]
|
||||
@@ -626,17 +620,104 @@ class StreamInterface(MeshInterface):
|
||||
traceback.print_exc()
|
||||
self._rxBuf = empty
|
||||
else:
|
||||
# logging.debug(f"timeout on {self.devPath}")
|
||||
# logging.debug(f"timeout")
|
||||
pass
|
||||
except serial.SerialException as ex:
|
||||
logging.warn(
|
||||
f"Meshtastic serial port disconnected, disconnecting... {ex}")
|
||||
finally:
|
||||
logging.debug("reader is exiting")
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = True # Return RTS high, so that the reset button still works
|
||||
self.stream.close()
|
||||
self._disconnected()</code></pre>
|
||||
self._disconnected()
|
||||
|
||||
|
||||
class SerialInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a serial link"""
|
||||
|
||||
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
|
||||
|
||||
Keyword Arguments:
|
||||
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} -- If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})
|
||||
"""
|
||||
|
||||
if devPath is None:
|
||||
ports = util.findPorts()
|
||||
if len(ports) == 0:
|
||||
raise Exception("No Meshtastic devices detected")
|
||||
elif len(ports) > 1:
|
||||
raise Exception(
|
||||
f"Multiple ports detected, you must specify a device, such as {ports[0].device}")
|
||||
else:
|
||||
devPath = ports[0]
|
||||
|
||||
logging.debug(f"Connecting to {devPath}")
|
||||
|
||||
# Note: we provide None for port here, because we will be opening it later
|
||||
self.stream = serial.Serial(
|
||||
None, 921600, exclusive=True, timeout=0.5)
|
||||
|
||||
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
|
||||
self.stream.port = devPath
|
||||
# OS-X seems to have a bug in its serial driver. It ignores that we asked for no RTSCTS
|
||||
# control and will always drive RTS either high or low (rather than letting the CP102 leave
|
||||
# it as an open-collector floating pin). Since it is going to drive it anyways we want to make
|
||||
# sure it is driven low, so that the TBEAM won't reset
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = False
|
||||
self.stream.open()
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
|
||||
|
||||
def _disconnected(self):
|
||||
"""We override the superclass implementation to close our port"""
|
||||
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = True # Return RTS high, so that the reset button still works
|
||||
|
||||
StreamInterface._disconnected(self)
|
||||
|
||||
|
||||
class TCPInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a TCP link"""
|
||||
|
||||
def __init__(self, hostname, debugOut=None, noProto=False, connectNow=True, portNumber=4403):
|
||||
"""Constructor, opens a connection to a specified IP address/hostname
|
||||
|
||||
Keyword Arguments:
|
||||
hostname {string} -- Hostname/IP address of the device to connect to
|
||||
"""
|
||||
|
||||
logging.debug(f"Connecting to {hostname}")
|
||||
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
|
||||
# Instead of wrapping as a stream, we use the native socket API
|
||||
# self.stream = sock.makefile('rw')
|
||||
self.stream = None
|
||||
self.socket = sock
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
|
||||
|
||||
def _disconnected(self):
|
||||
"""We override the superclass implementation to close our port"""
|
||||
StreamInterface._disconnected(self)
|
||||
|
||||
logging.debug("Closing our socket")
|
||||
if not self.socket is None:
|
||||
self.socket.close()
|
||||
|
||||
def _writeBytes(self, b):
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
self.socket.send(b)
|
||||
|
||||
def _readBytes(self, len):
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.socket.recv(len)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
@@ -961,10 +1042,12 @@ debugOut</p>
|
||||
elif fromRadio.HasField("packet"):
|
||||
self._handlePacketFromRadio(fromRadio.packet)
|
||||
elif fromRadio.rebooted:
|
||||
self._disconnected()
|
||||
# Tell clients the device went away. Careful not to call the overridden subclass version that closes the serial port
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
self._startConfig() # redownload the node db etc...
|
||||
else:
|
||||
logging.warn("Unexpected FromRadio payload")
|
||||
logging.debug("Unexpected FromRadio payload")
|
||||
|
||||
def _fixupPosition(self, position):
|
||||
"""Convert integer lat/lon into floats
|
||||
@@ -1244,16 +1327,100 @@ wantAck – True if you want the message sent in a reliable manner (with ret
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt id="meshtastic.StreamInterface"><code class="flex name class">
|
||||
<span>class <span class="ident">StreamInterface</span></span>
|
||||
<dt id="meshtastic.SerialInterface"><code class="flex name class">
|
||||
<span>class <span class="ident">SerialInterface</span></span>
|
||||
<span>(</span><span>devPath=None, debugOut=None, noProto=False, connectNow=True)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Interface class for meshtastic devices over a stream link (serial, TCP, etc)</p>
|
||||
<div class="desc"><p>Interface class for meshtastic devices over a serial link</p>
|
||||
<p>Constructor, opens a connection to a specified serial port, or if unspecified try to
|
||||
find one Meshtastic device by probing</p>
|
||||
<p>Keyword Arguments:
|
||||
devPath {string} – A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} – If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class SerialInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a serial link"""
|
||||
|
||||
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
|
||||
|
||||
Keyword Arguments:
|
||||
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} -- If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})
|
||||
"""
|
||||
|
||||
if devPath is None:
|
||||
ports = util.findPorts()
|
||||
if len(ports) == 0:
|
||||
raise Exception("No Meshtastic devices detected")
|
||||
elif len(ports) > 1:
|
||||
raise Exception(
|
||||
f"Multiple ports detected, you must specify a device, such as {ports[0].device}")
|
||||
else:
|
||||
devPath = ports[0]
|
||||
|
||||
logging.debug(f"Connecting to {devPath}")
|
||||
|
||||
# Note: we provide None for port here, because we will be opening it later
|
||||
self.stream = serial.Serial(
|
||||
None, 921600, exclusive=True, timeout=0.5)
|
||||
|
||||
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
|
||||
self.stream.port = devPath
|
||||
# OS-X seems to have a bug in its serial driver. It ignores that we asked for no RTSCTS
|
||||
# control and will always drive RTS either high or low (rather than letting the CP102 leave
|
||||
# it as an open-collector floating pin). Since it is going to drive it anyways we want to make
|
||||
# sure it is driven low, so that the TBEAM won't reset
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = False
|
||||
self.stream.open()
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
|
||||
|
||||
def _disconnected(self):
|
||||
"""We override the superclass implementation to close our port"""
|
||||
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = True # Return RTS high, so that the reset button still works
|
||||
|
||||
StreamInterface._disconnected(self)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="meshtastic.StreamInterface" href="#meshtastic.StreamInterface">StreamInterface</a></li>
|
||||
<li><a title="meshtastic.MeshInterface" href="#meshtastic.MeshInterface">MeshInterface</a></li>
|
||||
</ul>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="meshtastic.StreamInterface" href="#meshtastic.StreamInterface">StreamInterface</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="meshtastic.StreamInterface.channelURL" href="#meshtastic.MeshInterface.channelURL">channelURL</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.close" href="#meshtastic.StreamInterface.close">close</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.connect" href="#meshtastic.StreamInterface.connect">connect</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendData" href="#meshtastic.MeshInterface.sendData">sendData</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendPacket" href="#meshtastic.MeshInterface.sendPacket">sendPacket</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendPosition" href="#meshtastic.MeshInterface.sendPosition">sendPosition</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendText" href="#meshtastic.MeshInterface.sendText">sendText</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.writeConfig" href="#meshtastic.MeshInterface.writeConfig">writeConfig</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt id="meshtastic.StreamInterface"><code class="flex name class">
|
||||
<span>class <span class="ident">StreamInterface</span></span>
|
||||
<span>(</span><span>debugOut=None, noProto=False, connectNow=True)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Interface class for meshtastic devices over a stream link (serial, TCP, etc)</p>
|
||||
<p>Constructor, opens a connection to self.stream </p>
|
||||
<p>Keyword Arguments:
|
||||
devPath {string} – A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} – If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})</p>
|
||||
<h2 id="raises">Raises</h2>
|
||||
<dl>
|
||||
@@ -1269,9 +1436,8 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
<pre><code class="python">class StreamInterface(MeshInterface):
|
||||
"""Interface class for meshtastic devices over a stream link (serial, TCP, etc)"""
|
||||
|
||||
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
|
||||
def __init__(self, debugOut=None, noProto=False, connectNow=True):
|
||||
"""Constructor, opens a connection to self.stream
|
||||
|
||||
Keyword Arguments:
|
||||
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
@@ -1282,35 +1448,12 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
Exception: [description]
|
||||
"""
|
||||
|
||||
if devPath is None:
|
||||
ports = util.findPorts()
|
||||
if len(ports) == 0:
|
||||
raise Exception("No Meshtastic devices detected")
|
||||
elif len(ports) > 1:
|
||||
raise Exception(
|
||||
f"Multiple ports detected, you must specify a device, such as {ports[0].device}")
|
||||
else:
|
||||
devPath = ports[0]
|
||||
|
||||
logging.debug(f"Connecting to {devPath}")
|
||||
self.devPath = devPath
|
||||
if not hasattr(self, 'stream'):
|
||||
raise Exception(
|
||||
"StreamInterface is now abstract (to update existing code create SerialInterface instead)")
|
||||
self._rxBuf = bytes() # empty
|
||||
self._wantExit = False
|
||||
|
||||
# Note: we provide None for port here, because we will be opening it later
|
||||
self.stream = serial.Serial(
|
||||
None, 921600, exclusive=True, timeout=0.5)
|
||||
|
||||
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
|
||||
self.stream.port = devPath
|
||||
# OS-X seems to have a bug in its serial driver. It ignores that we asked for no RTSCTS
|
||||
# control and will always drive RTS either high or low (rather than letting the CP102 leave
|
||||
# it as an open-collector floating pin). Since it is going to drive it anyways we want to make
|
||||
# sure it is driven low, so that the TBEAM won't reset
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = False
|
||||
self.stream.open()
|
||||
|
||||
self._rxThread = threading.Thread(target=self.__reader, args=())
|
||||
|
||||
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
|
||||
@@ -1327,21 +1470,36 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
"""
|
||||
|
||||
# Send some bogus UART characters to force a sleeping device to wake
|
||||
self.stream.write(bytes([START1, START1, START1, START1]))
|
||||
self.stream.flush()
|
||||
self._writeBytes(bytes([START1, START1, START1, START1]))
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
self._rxThread.start()
|
||||
|
||||
def _disconnected(self):
|
||||
"""We override the superclass implementation to close our port"""
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
logging.debug("Closing our port")
|
||||
if not self.stream is None:
|
||||
self.stream.close()
|
||||
|
||||
def _writeBytes(self, b):
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
self.stream.write(b)
|
||||
self.stream.flush()
|
||||
|
||||
def _readBytes(self, len):
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.stream.read(len)
|
||||
|
||||
def _sendToRadio(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {toRadio}")
|
||||
b = toRadio.SerializeToString()
|
||||
bufLen = len(b)
|
||||
# We convert into a string, because the TCP code doesn't work with byte arrays
|
||||
header = bytes([START1, START2, (bufLen >> 8) & 0xff, bufLen & 0xff])
|
||||
self.stream.write(header)
|
||||
self.stream.write(b)
|
||||
self.stream.flush()
|
||||
self._writeBytes(header + b)
|
||||
|
||||
def close(self):
|
||||
"""Close a connection to the device"""
|
||||
@@ -1357,7 +1515,7 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
|
||||
try:
|
||||
while not self._wantExit:
|
||||
b = self.stream.read(1)
|
||||
b = self._readBytes(1)
|
||||
if len(b) > 0:
|
||||
# logging.debug(f"read returned {b}")
|
||||
c = b[0]
|
||||
@@ -1395,22 +1553,24 @@ debugOut {stream} – If a stream is provided, any debug serial output from
|
||||
traceback.print_exc()
|
||||
self._rxBuf = empty
|
||||
else:
|
||||
# logging.debug(f"timeout on {self.devPath}")
|
||||
# logging.debug(f"timeout")
|
||||
pass
|
||||
except serial.SerialException as ex:
|
||||
logging.warn(
|
||||
f"Meshtastic serial port disconnected, disconnecting... {ex}")
|
||||
finally:
|
||||
logging.debug("reader is exiting")
|
||||
if platform.system() == 'Darwin':
|
||||
self.stream.rts = True # Return RTS high, so that the reset button still works
|
||||
self.stream.close()
|
||||
self._disconnected()</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="meshtastic.MeshInterface" href="#meshtastic.MeshInterface">MeshInterface</a></li>
|
||||
</ul>
|
||||
<h3>Subclasses</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="meshtastic.SerialInterface" href="#meshtastic.SerialInterface">SerialInterface</a></li>
|
||||
<li><a title="meshtastic.TCPInterface" href="#meshtastic.TCPInterface">TCPInterface</a></li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.StreamInterface.close"><code class="name flex">
|
||||
@@ -1450,8 +1610,7 @@ start the reading thread later.</p></div>
|
||||
"""
|
||||
|
||||
# Send some bogus UART characters to force a sleeping device to wake
|
||||
self.stream.write(bytes([START1, START1, START1, START1]))
|
||||
self.stream.flush()
|
||||
self._writeBytes(bytes([START1, START1, START1, START1]))
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
self._rxThread.start()</code></pre>
|
||||
@@ -1472,6 +1631,79 @@ start the reading thread later.</p></div>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt id="meshtastic.TCPInterface"><code class="flex name class">
|
||||
<span>class <span class="ident">TCPInterface</span></span>
|
||||
<span>(</span><span>hostname, debugOut=None, noProto=False, connectNow=True, portNumber=4403)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Interface class for meshtastic devices over a TCP link</p>
|
||||
<p>Constructor, opens a connection to a specified IP address/hostname</p>
|
||||
<p>Keyword Arguments:
|
||||
hostname {string} – Hostname/IP address of the device to connect to</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">class TCPInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a TCP link"""
|
||||
|
||||
def __init__(self, hostname, debugOut=None, noProto=False, connectNow=True, portNumber=4403):
|
||||
"""Constructor, opens a connection to a specified IP address/hostname
|
||||
|
||||
Keyword Arguments:
|
||||
hostname {string} -- Hostname/IP address of the device to connect to
|
||||
"""
|
||||
|
||||
logging.debug(f"Connecting to {hostname}")
|
||||
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
|
||||
# Instead of wrapping as a stream, we use the native socket API
|
||||
# self.stream = sock.makefile('rw')
|
||||
self.stream = None
|
||||
self.socket = sock
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
|
||||
|
||||
def _disconnected(self):
|
||||
"""We override the superclass implementation to close our port"""
|
||||
StreamInterface._disconnected(self)
|
||||
|
||||
logging.debug("Closing our socket")
|
||||
if not self.socket is None:
|
||||
self.socket.close()
|
||||
|
||||
def _writeBytes(self, b):
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
self.socket.send(b)
|
||||
|
||||
def _readBytes(self, len):
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.socket.recv(len)</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li><a title="meshtastic.StreamInterface" href="#meshtastic.StreamInterface">StreamInterface</a></li>
|
||||
<li><a title="meshtastic.MeshInterface" href="#meshtastic.MeshInterface">MeshInterface</a></li>
|
||||
</ul>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="meshtastic.StreamInterface" href="#meshtastic.StreamInterface">StreamInterface</a></b></code>:
|
||||
<ul class="hlist">
|
||||
<li><code><a title="meshtastic.StreamInterface.channelURL" href="#meshtastic.MeshInterface.channelURL">channelURL</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.close" href="#meshtastic.StreamInterface.close">close</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.connect" href="#meshtastic.StreamInterface.connect">connect</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendData" href="#meshtastic.MeshInterface.sendData">sendData</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendPacket" href="#meshtastic.MeshInterface.sendPacket">sendPacket</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendPosition" href="#meshtastic.MeshInterface.sendPosition">sendPosition</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.sendText" href="#meshtastic.MeshInterface.sendText">sendText</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.writeConfig" href="#meshtastic.MeshInterface.writeConfig">writeConfig</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
@@ -1518,12 +1750,18 @@ start the reading thread later.</p></div>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.SerialInterface" href="#meshtastic.SerialInterface">SerialInterface</a></code></h4>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.StreamInterface" href="#meshtastic.StreamInterface">StreamInterface</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.StreamInterface.close" href="#meshtastic.StreamInterface.close">close</a></code></li>
|
||||
<li><code><a title="meshtastic.StreamInterface.connect" href="#meshtastic.StreamInterface.connect">connect</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.TCPInterface" href="#meshtastic.TCPInterface">TCPInterface</a></code></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -26,7 +26,7 @@
|
||||
</summary>
|
||||
<pre><code class="python">import logging
|
||||
from . import util
|
||||
from . import StreamInterface, BROADCAST_NUM
|
||||
from . import SerialInterface, BROADCAST_NUM
|
||||
from pubsub import pub
|
||||
import time
|
||||
import sys
|
||||
@@ -154,7 +154,7 @@ def testAll():
|
||||
pub.subscribe(onConnection, "meshtastic.connection")
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
global interfaces
|
||||
interfaces = list(map(lambda port: StreamInterface(
|
||||
interfaces = list(map(lambda port: SerialInterface(
|
||||
port, debugOut=openDebugLog(port), connectNow=False), ports))
|
||||
for i in interfaces:
|
||||
i.connect()
|
||||
@@ -288,7 +288,7 @@ def testAll():
|
||||
pub.subscribe(onConnection, "meshtastic.connection")
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
global interfaces
|
||||
interfaces = list(map(lambda port: StreamInterface(
|
||||
interfaces = list(map(lambda port: SerialInterface(
|
||||
port, debugOut=openDebugLog(port), connectNow=False), ports))
|
||||
for i in interfaces:
|
||||
i.connect()
|
||||
|
||||
@@ -276,7 +276,9 @@ class MeshInterface:
|
||||
elif fromRadio.HasField("packet"):
|
||||
self._handlePacketFromRadio(fromRadio.packet)
|
||||
elif fromRadio.rebooted:
|
||||
self._disconnected()
|
||||
# Tell clients the device went away. Careful not to call the overridden subclass version that closes the serial port
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
self._startConfig() # redownload the node db etc...
|
||||
else:
|
||||
logging.debug("Unexpected FromRadio payload")
|
||||
|
||||
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.0.11",
|
||||
version="1.0.13",
|
||||
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