diff --git a/docs/meshtastic/index.html b/docs/meshtastic/index.html
index 4b22122..88ff96f 100644
--- a/docs/meshtastic/index.html
+++ b/docs/meshtastic/index.html
@@ -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()
-class StreamInterface
+
+class SerialInterface
(devPath=None, debugOut=None, noProto=False, connectNow=True)
-Interface class for meshtastic devices over a stream link (serial, TCP, etc)
+Interface class for meshtastic devices over a serial link
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})
+
+
+Expand source code
+
+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)
+
+Ancestors
+
+Inherited members
+
+StreamInterface:
+
+
+
+
+
+class StreamInterface
+(debugOut=None, noProto=False, connectNow=True)
+
+
+Interface class for meshtastic devices over a stream link (serial, TCP, etc)
+Constructor, opens a connection to self.stream
+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})
Raises
@@ -1269,9 +1436,8 @@ 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, 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()
Ancestors
+Subclasses
+
Methods
@@ -1450,8 +1610,7 @@ 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()
+ self._writeBytes(bytes([START1, START1, START1, START1]))
time.sleep(0.1) # wait 100ms to give device time to start running
self._rxThread.start()
@@ -1472,6 +1631,79 @@ start the reading thread later.
+
+class TCPInterface
+(hostname, debugOut=None, noProto=False, connectNow=True, portNumber=4403)
+
+
+Interface class for meshtastic devices over a TCP link
+Constructor, opens a connection to a specified IP address/hostname
+Keyword Arguments:
+hostname {string} – Hostname/IP address of the device to connect to
+
+
+Expand source code
+
+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)
+
+Ancestors
+
+Inherited members
+
+StreamInterface:
+
+
+
+
@@ -1518,12 +1750,18 @@ start the reading thread later.
+SerialInterface
+
+
StreamInterface
+
+TCPInterface
+
diff --git a/docs/meshtastic/mesh_pb2.html b/docs/meshtastic/mesh_pb2.html
index 5f990e9..dec38f9 100644
--- a/docs/meshtastic/mesh_pb2.html
+++ b/docs/meshtastic/mesh_pb2.html
@@ -46,7 +46,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
package='',
syntax='proto3',
serialized_options=_b('\n\023com.geeksville.meshB\nMeshProtos'),
- serialized_pb=_b('\n\nmesh.proto\"j\n\x08Position\x12\x12\n\nlatitude_i\x18\x07 \x01(\x11\x12\x13\n\x0blongitude_i\x18\x08 \x01(\x11\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x15\n\rbattery_level\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\t \x01(\x07\"g\n\x04\x44\x61ta\x12\x17\n\x03typ\x18\x01 \x01(\x0e\x32\n.Data.Type\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"5\n\x04Type\x12\n\n\x06OPAQUE\x10\x00\x12\x0e\n\nCLEAR_TEXT\x10\x01\x12\x11\n\rCLEAR_READACK\x10\x02\"J\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x0f\n\x07macaddr\x18\x04 \x01(\x0c\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x05\"\xd3\x02\n\tSubPacket\x12\x1d\n\x08position\x18\x01 \x01(\x0b\x32\t.PositionH\x00\x12\x15\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x05.DataH\x00\x12\x15\n\x04user\x18\x04 \x01(\x0b\x32\x05.UserH\x00\x12(\n\rroute_request\x18\x06 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x07 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12\"\n\x0broute_error\x18\r \x01(\x0e\x32\x0b.RouteErrorH\x00\x12\x15\n\rwant_response\x18\x05 \x01(\x08\x12\x14\n\nsuccess_id\x18\n \x01(\rH\x01\x12\x11\n\x07\x66\x61il_id\x18\x0b \x01(\rH\x01\x12\x0c\n\x04\x64\x65st\x18\t \x01(\r\x12\x0e\n\x06source\x18\x0c \x01(\r\x12\x13\n\x0boriginal_id\x18\x02 \x01(\rB\t\n\x07payloadB\x05\n\x03\x61\x63k\"\xb7\x01\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\r\x12\n\n\x02to\x18\x02 \x01(\r\x12\x1d\n\x07\x64\x65\x63oded\x18\x03 \x01(\x0b\x32\n.SubPacketH\x00\x12\x13\n\tencrypted\x18\x08 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\r\x12\x0f\n\x07rx_time\x18\t \x01(\x07\x12\x0e\n\x06rx_snr\x18\x07 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x42\t\n\x07payload\"\xa8\x02\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\"`\n\x0bModemConfig\x12\x12\n\x0e\x42w125Cr45Sf128\x10\x00\x12\x12\n\x0e\x42w500Cr45Sf128\x10\x01\x12\x14\n\x10\x42w31_25Cr48Sf512\x10\x02\x12\x13\n\x0f\x42w125Cr48Sf4096\x10\x03\"\xfc\x03\n\x0bRadioConfig\x12\x31\n\x0bpreferences\x18\x01 \x01(\x0b\x32\x1c.RadioConfig.UserPreferences\x12*\n\x10\x63hannel_settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x1a\x8d\x03\n\x0fUserPreferences\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12\x1b\n\x13send_owner_interval\x18\x02 \x01(\r\x12\x1a\n\x12num_missed_to_fail\x18\x03 \x01(\r\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x16\n\x0escreen_on_secs\x18\x05 \x01(\r\x12\x1a\n\x12phone_timeout_secs\x18\x06 \x01(\r\x12\x1d\n\x15phone_sds_timeout_sec\x18\x07 \x01(\r\x12\x1d\n\x15mesh_sds_timeout_secs\x18\x08 \x01(\r\x12\x10\n\x08sds_secs\x18\t \x01(\r\x12\x0f\n\x07ls_secs\x18\n \x01(\r\x12\x15\n\rmin_wake_secs\x18\x0b \x01(\r\x12\x11\n\twifi_ssid\x18\x0c \x01(\t\x12\x15\n\rwifi_password\x18\r \x01(\t\x12\x14\n\x0cwifi_ap_mode\x18\x0e \x01(\x08\x12\x17\n\x0fignore_incoming\x18\x66 \x03(\r\"h\n\x08NodeInfo\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x13\n\x04user\x18\x02 \x01(\x0b\x32\x05.User\x12\x1b\n\x08position\x18\x03 \x01(\x0b\x32\t.Position\x12\x0b\n\x03snr\x18\x07 \x01(\x02\x12\x10\n\x08next_hop\x18\x05 \x01(\r\"\xc5\x02\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x14\n\x0cnum_channels\x18\x03 \x01(\x05\x12\x0e\n\x06region\x18\x04 \x01(\t\x12\x10\n\x08hw_model\x18\x05 \x01(\t\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12\x12\n\nerror_code\x18\x07 \x01(\r\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x16\n\x0epacket_id_bits\x18\n \x01(\r\x12\x19\n\x11\x63urrent_packet_id\x18\x0b \x01(\r\x12\x15\n\rnode_num_bits\x18\x0c \x01(\r\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\"\xfd\x01\n\x0b\x44\x65viceState\x12\x1b\n\x05radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfig\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\"\x1e\n\x0b\x44\x65\x62ugString\x12\x0f\n\x07message\x18\x01 \x01(\t\"\xf9\x01\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x1e\n\x07my_info\x18\x03 \x01(\x0b\x32\x0b.MyNodeInfoH\x00\x12\x1e\n\tnode_info\x18\x04 \x01(\x0b\x32\t.NodeInfoH\x00\x12\x1d\n\x05radio\x18\x06 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12$\n\x0c\x64\x65\x62ug_string\x18\x07 \x01(\x0b\x32\x0c.DebugStringH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x42\t\n\x07variant\"\x8c\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12!\n\tset_radio\x18\x65 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x66 \x01(\x0b\x32\x05.UserH\x00\x42\t\n\x07variant\"f\n\x11ManufacturingData\x12\x12\n\nfradioFreq\x18\x01 \x01(\r\x12\x10\n\x08hw_model\x18\x02 \x01(\t\x12\x12\n\nhw_version\x18\x03 \x01(\t\x12\x17\n\x0fselftest_result\x18\x04 \x01(\x11*>\n\nRouteError\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03*\x17\n\tConstants\x12\n\n\x06Unused\x10\x00\x42!\n\x13\x63om.geeksville.meshB\nMeshProtosb\x06proto3')
+ serialized_pb=_b('\n\nmesh.proto\"j\n\x08Position\x12\x12\n\nlatitude_i\x18\x07 \x01(\x11\x12\x13\n\x0blongitude_i\x18\x08 \x01(\x11\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x15\n\rbattery_level\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\t \x01(\x07\"g\n\x04\x44\x61ta\x12\x17\n\x03typ\x18\x01 \x01(\x0e\x32\n.Data.Type\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"5\n\x04Type\x12\n\n\x06OPAQUE\x10\x00\x12\x0e\n\nCLEAR_TEXT\x10\x01\x12\x11\n\rCLEAR_READACK\x10\x02\"J\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x0f\n\x07macaddr\x18\x04 \x01(\x0c\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x05\"\xd3\x02\n\tSubPacket\x12\x1d\n\x08position\x18\x01 \x01(\x0b\x32\t.PositionH\x00\x12\x15\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x05.DataH\x00\x12\x15\n\x04user\x18\x04 \x01(\x0b\x32\x05.UserH\x00\x12(\n\rroute_request\x18\x06 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x07 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12\"\n\x0broute_error\x18\r \x01(\x0e\x32\x0b.RouteErrorH\x00\x12\x15\n\rwant_response\x18\x05 \x01(\x08\x12\x14\n\nsuccess_id\x18\n \x01(\rH\x01\x12\x11\n\x07\x66\x61il_id\x18\x0b \x01(\rH\x01\x12\x0c\n\x04\x64\x65st\x18\t \x01(\r\x12\x0e\n\x06source\x18\x0c \x01(\r\x12\x13\n\x0boriginal_id\x18\x02 \x01(\rB\t\n\x07payloadB\x05\n\x03\x61\x63k\"\xb7\x01\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\r\x12\n\n\x02to\x18\x02 \x01(\r\x12\x1d\n\x07\x64\x65\x63oded\x18\x03 \x01(\x0b\x32\n.SubPacketH\x00\x12\x13\n\tencrypted\x18\x08 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\r\x12\x0f\n\x07rx_time\x18\t \x01(\x07\x12\x0e\n\x06rx_snr\x18\x07 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x42\t\n\x07payload\"\xa8\x02\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\"`\n\x0bModemConfig\x12\x12\n\x0e\x42w125Cr45Sf128\x10\x00\x12\x12\n\x0e\x42w500Cr45Sf128\x10\x01\x12\x14\n\x10\x42w31_25Cr48Sf512\x10\x02\x12\x13\n\x0f\x42w125Cr48Sf4096\x10\x03\"\xa3\x04\n\x0bRadioConfig\x12\x31\n\x0bpreferences\x18\x01 \x01(\x0b\x32\x1c.RadioConfig.UserPreferences\x12*\n\x10\x63hannel_settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x1a\xb4\x03\n\x0fUserPreferences\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12\x1b\n\x13send_owner_interval\x18\x02 \x01(\r\x12\x1a\n\x12num_missed_to_fail\x18\x03 \x01(\r\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x16\n\x0escreen_on_secs\x18\x05 \x01(\r\x12\x1a\n\x12phone_timeout_secs\x18\x06 \x01(\r\x12\x1d\n\x15phone_sds_timeout_sec\x18\x07 \x01(\r\x12\x1d\n\x15mesh_sds_timeout_secs\x18\x08 \x01(\r\x12\x10\n\x08sds_secs\x18\t \x01(\r\x12\x0f\n\x07ls_secs\x18\n \x01(\r\x12\x15\n\rmin_wake_secs\x18\x0b \x01(\r\x12\x11\n\twifi_ssid\x18\x0c \x01(\t\x12\x15\n\rwifi_password\x18\r \x01(\t\x12\x14\n\x0cwifi_ap_mode\x18\x0e \x01(\x08\x12\x0e\n\x06region\x18\x0f \x01(\t\x12\x15\n\rfactory_reset\x18\x64 \x01(\x08\x12\x17\n\x0fignore_incoming\x18g \x03(\r\"h\n\x08NodeInfo\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x13\n\x04user\x18\x02 \x01(\x0b\x32\x05.User\x12\x1b\n\x08position\x18\x03 \x01(\x0b\x32\t.Position\x12\x0b\n\x03snr\x18\x07 \x01(\x02\x12\x10\n\x08next_hop\x18\x05 \x01(\r\"\xc5\x02\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x14\n\x0cnum_channels\x18\x03 \x01(\x05\x12\x0e\n\x06region\x18\x04 \x01(\t\x12\x10\n\x08hw_model\x18\x05 \x01(\t\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12\x12\n\nerror_code\x18\x07 \x01(\r\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x16\n\x0epacket_id_bits\x18\n \x01(\r\x12\x19\n\x11\x63urrent_packet_id\x18\x0b \x01(\r\x12\x15\n\rnode_num_bits\x18\x0c \x01(\r\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\"\xfd\x01\n\x0b\x44\x65viceState\x12\x1b\n\x05radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfig\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\"\x1e\n\x0b\x44\x65\x62ugString\x12\x0f\n\x07message\x18\x01 \x01(\t\"\xf9\x01\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x1e\n\x07my_info\x18\x03 \x01(\x0b\x32\x0b.MyNodeInfoH\x00\x12\x1e\n\tnode_info\x18\x04 \x01(\x0b\x32\t.NodeInfoH\x00\x12\x1d\n\x05radio\x18\x06 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12$\n\x0c\x64\x65\x62ug_string\x18\x07 \x01(\x0b\x32\x0c.DebugStringH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x42\t\n\x07variant\"\x8c\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12!\n\tset_radio\x18\x65 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x66 \x01(\x0b\x32\x05.UserH\x00\x42\t\n\x07variant\"f\n\x11ManufacturingData\x12\x12\n\nfradioFreq\x18\x01 \x01(\r\x12\x10\n\x08hw_model\x18\x02 \x01(\t\x12\x12\n\nhw_version\x18\x03 \x01(\t\x12\x17\n\x0fselftest_result\x18\x04 \x01(\x11*>\n\nRouteError\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03*\x17\n\tConstants\x12\n\n\x06Unused\x10\x00\x42!\n\x13\x63om.geeksville.meshB\nMeshProtosb\x06proto3')
)
_ROUTEERROR = _descriptor.EnumDescriptor(
@@ -74,8 +74,8 @@ _ROUTEERROR = _descriptor.EnumDescriptor(
],
containing_type=None,
serialized_options=None,
- serialized_start=2895,
- serialized_end=2957,
+ serialized_start=2934,
+ serialized_end=2996,
)
_sym_db.RegisterEnumDescriptor(_ROUTEERROR)
@@ -93,8 +93,8 @@ _CONSTANTS = _descriptor.EnumDescriptor(
],
containing_type=None,
serialized_options=None,
- serialized_start=2959,
- serialized_end=2982,
+ serialized_start=2998,
+ serialized_end=3021,
)
_sym_db.RegisterEnumDescriptor(_CONSTANTS)
@@ -735,8 +735,22 @@ _RADIOCONFIG_USERPREFERENCES = _descriptor.Descriptor(
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='ignore_incoming', full_name='RadioConfig.UserPreferences.ignore_incoming', index=14,
- number=102, type=13, cpp_type=3, label=3,
+ name='region', full_name='RadioConfig.UserPreferences.region', index=14,
+ number=15, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='factory_reset', full_name='RadioConfig.UserPreferences.factory_reset', index=15,
+ number=100, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='ignore_incoming', full_name='RadioConfig.UserPreferences.ignore_incoming', index=16,
+ number=103, type=13, cpp_type=3, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
@@ -754,7 +768,7 @@ _RADIOCONFIG_USERPREFERENCES = _descriptor.Descriptor(
oneofs=[
],
serialized_start=1275,
- serialized_end=1672,
+ serialized_end=1711,
)
_RADIOCONFIG = _descriptor.Descriptor(
@@ -791,7 +805,7 @@ _RADIOCONFIG = _descriptor.Descriptor(
oneofs=[
],
serialized_start=1164,
- serialized_end=1672,
+ serialized_end=1711,
)
@@ -849,8 +863,8 @@ _NODEINFO = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=1674,
- serialized_end=1778,
+ serialized_start=1713,
+ serialized_end=1817,
)
@@ -971,8 +985,8 @@ _MYNODEINFO = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=1781,
- serialized_end=2106,
+ serialized_start=1820,
+ serialized_end=2145,
)
@@ -1058,8 +1072,8 @@ _DEVICESTATE = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2109,
- serialized_end=2362,
+ serialized_start=2148,
+ serialized_end=2401,
)
@@ -1089,8 +1103,8 @@ _DEBUGSTRING = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2364,
- serialized_end=2394,
+ serialized_start=2403,
+ serialized_end=2433,
)
@@ -1172,8 +1186,8 @@ _FROMRADIO = _descriptor.Descriptor(
name='variant', full_name='FromRadio.variant',
index=0, containing_type=None, fields=[]),
],
- serialized_start=2397,
- serialized_end=2646,
+ serialized_start=2436,
+ serialized_end=2685,
)
@@ -1227,8 +1241,8 @@ _TORADIO = _descriptor.Descriptor(
name='variant', full_name='ToRadio.variant',
index=0, containing_type=None, fields=[]),
],
- serialized_start=2649,
- serialized_end=2789,
+ serialized_start=2688,
+ serialized_end=2828,
)
@@ -1279,8 +1293,8 @@ _MANUFACTURINGDATA = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2791,
- serialized_end=2893,
+ serialized_start=2830,
+ serialized_end=2932,
)
_DATA.fields_by_name['typ'].enum_type = _DATA_TYPE
diff --git a/docs/meshtastic/test.html b/docs/meshtastic/test.html
index b1cd793..e921b65 100644
--- a/docs/meshtastic/test.html
+++ b/docs/meshtastic/test.html
@@ -26,7 +26,7 @@
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()
diff --git a/meshtastic/__init__.py b/meshtastic/__init__.py
index 437b76a..43aa496 100644
--- a/meshtastic/__init__.py
+++ b/meshtastic/__init__.py
@@ -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")
diff --git a/setup.py b/setup.py
index ddf920e..54e889d 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.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",