diff --git a/docs/meshtastic/index.html b/docs/meshtastic/index.html index 7f233c7..e44ae16 100644 --- a/docs/meshtastic/index.html +++ b/docs/meshtastic/index.html @@ -154,11 +154,14 @@ import time import base64 import platform import socket +import timeago 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, stripnl, DeferredExecution, Timeout from .node import Node from pubsub import pub from dotmap import DotMap +from datetime import datetime +from tabulate import tabulate from typing import * from google.protobuf.json_format import MessageToJson @@ -247,12 +250,65 @@ class MeshInterface: logging.error(f'Traceback: {traceback}') self.close() - def showInfo(self): + def showInfo(self, file=sys.stdout): """Show human readable summary about this object""" - print(f"My info: {stripnl(MessageToJson(self.myInfo))}") - print("\nNodes in mesh:") + + print(f"Owner: {self.getLongName()} ({self.getShortName()})", file=file) + print(f"\nMy info: {stripnl(MessageToJson(self.myInfo))}", file=file) + print("\nNodes in mesh:", file=file) for n in self.nodes.values(): - print(" " + stripnl(n)) + print(f" {stripnl(n)}", file=file) + + def showNodes(self, includeSelf=True, file=sys.stdout): + """Show table summary of nodes in mesh""" + def formatFloat(value, precision=2, unit=''): + return f'{value:.{precision}f}{unit}' if value else None + + def getLH(ts): + return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') if ts else None + + def getTimeAgo(ts): + return timeago.format(datetime.fromtimestamp(ts), datetime.now()) if ts else None + + rows = [] + for node in self.nodes.values(): + if not includeSelf and node['num'] == self.localNode.nodeNum: + continue + + row = { "N": 0 } + + user = node.get('user') + if user: + row.update({ + "User": user['longName'], + "AKA": user['shortName'], + "ID": user['id'], + }) + + pos = node.get('position') + if pos: + row.update({ + "Latitude": formatFloat(pos.get("latitude"), 4, "°"), + "Longitude": formatFloat(pos.get("longitude"), 4, "°"), + "Altitude": formatFloat(pos.get("altitude"), 0, " m"), + "Battery": formatFloat(pos.get("batteryLevel"), 2, "%"), + }) + + row.update({ + "SNR": formatFloat(node.get("snr"), 2, " dB"), + "LastHeard": getLH( node.get("lastHeard")), + "Since": getTimeAgo( node.get("lastHeard")), + }) + + rows.append(row) + + # Why doesn't this way work? + #rows.sort(key=lambda r: r.get('LastHeard', '0000'), reverse=True) + rows.sort(key=lambda r: r.get('LastHeard') or '0000', reverse=True) + for i, row in enumerate(rows): + row['N'] = i+1 + + print(tabulate(rows, headers='keys', missingval='N/A', tablefmt='fancy_grid'), file=file) def getNode(self, nodeId): """Return a node object which contains device settings and channel info""" @@ -771,7 +827,7 @@ class StreamInterface(MeshInterface): self._wantExit = False # FIXME, figure out why daemon=True causes reader thread to exit too early - self._rxThread = threading.Thread(target=self.__reader, args=()) + self._rxThread = threading.Thread(target=self.__reader, args=(), daemon=True) MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto) @@ -1190,6 +1246,7 @@ noProto – If True, don't try to run our protocol on the link - just be a d
sendPositionsendTextshowInfoshowNodeswaitForConfig
-def showInfo(self)
+def showInfo(self, file=sys.stdout)
Show human readable summary about this object
def showInfo(self):
+def showInfo(self, file=sys.stdout):
"""Show human readable summary about this object"""
- print(f"My info: {stripnl(MessageToJson(self.myInfo))}")
- print("\nNodes in mesh:")
+
+ print(f"Owner: {self.getLongName()} ({self.getShortName()})", file=file)
+ print(f"\nMy info: {stripnl(MessageToJson(self.myInfo))}", file=file)
+ print("\nNodes in mesh:", file=file)
for n in self.nodes.values():
- print(" " + stripnl(n))
+ print(f" {stripnl(n)}", file=file)
+
+
+def showNodes(self, includeSelf=True, file=sys.stdout)
+Show table summary of nodes in mesh
def showNodes(self, includeSelf=True, file=sys.stdout):
+ """Show table summary of nodes in mesh"""
+ def formatFloat(value, precision=2, unit=''):
+ return f'{value:.{precision}f}{unit}' if value else None
+
+ def getLH(ts):
+ return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') if ts else None
+
+ def getTimeAgo(ts):
+ return timeago.format(datetime.fromtimestamp(ts), datetime.now()) if ts else None
+
+ rows = []
+ for node in self.nodes.values():
+ if not includeSelf and node['num'] == self.localNode.nodeNum:
+ continue
+
+ row = { "N": 0 }
+
+ user = node.get('user')
+ if user:
+ row.update({
+ "User": user['longName'],
+ "AKA": user['shortName'],
+ "ID": user['id'],
+ })
+
+ pos = node.get('position')
+ if pos:
+ row.update({
+ "Latitude": formatFloat(pos.get("latitude"), 4, "°"),
+ "Longitude": formatFloat(pos.get("longitude"), 4, "°"),
+ "Altitude": formatFloat(pos.get("altitude"), 0, " m"),
+ "Battery": formatFloat(pos.get("batteryLevel"), 2, "%"),
+ })
+
+ row.update({
+ "SNR": formatFloat(node.get("snr"), 2, " dB"),
+ "LastHeard": getLH( node.get("lastHeard")),
+ "Since": getTimeAgo( node.get("lastHeard")),
+ })
+
+ rows.append(row)
+
+ # Why doesn't this way work?
+ #rows.sort(key=lambda r: r.get('LastHeard', '0000'), reverse=True)
+ rows.sort(key=lambda r: r.get('LastHeard') or '0000', reverse=True)
+ for i, row in enumerate(rows):
+ row['N'] = i+1
+
+ print(tabulate(rows, headers='keys', missingval='N/A', tablefmt='fancy_grid'), file=file)
@@ -2138,6 +2311,7 @@ debugOut {stream} – If a stream is provided, any debug serial output from
sendPosition
sendText
showInfo
+showNodes
waitForConfig
@@ -2186,7 +2360,7 @@ debugOut {stream} – If a stream is provided, any debug serial output from
self._wantExit = False
# FIXME, figure out why daemon=True causes reader thread to exit too early
- self._rxThread = threading.Thread(target=self.__reader, args=())
+ self._rxThread = threading.Thread(target=self.__reader, args=(), daemon=True)
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
@@ -2378,6 +2552,7 @@ start the reading thread later.
sendPosition
sendText
showInfo
+showNodes
waitForConfig
@@ -2457,6 +2632,7 @@ hostname {string} – Hostname/IP address of the device to connect tosendPosition
sendText
showInfo
+showNodes
waitForConfig
@@ -2528,6 +2704,7 @@ hostname {string} – Hostname/IP address of the device to connect tosendPosition
sendText
showInfo
+showNodes
waitForConfig
diff --git a/docs/meshtastic/mesh_pb2.html b/docs/meshtastic/mesh_pb2.html
index 3070ba9..a3f8e4a 100644
--- a/docs/meshtastic/mesh_pb2.html
+++ b/docs/meshtastic/mesh_pb2.html
@@ -50,7 +50,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\nMeshProtosH\003',
create_key=_descriptor._internal_create_key,
- serialized_pb=b'\n\nmesh.proto\x1a\x0eportnums.proto\"v\n\x08Position\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\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(\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t\"\x81\x01\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\x12 \n\x08hw_model\x18\x06 \x01(\x0e\x32\x0e.HardwareModel\x12\x13\n\x0bis_licensed\x18\x07 \x01(\x08\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x07\"\xc5\x02\n\x07Routing\x12(\n\rroute_request\x18\x01 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x02 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0c\x65rror_reason\x18\x03 \x01(\x0e\x32\x0e.Routing.ErrorH\x00\"\xb4\x01\n\x05\x45rror\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\x12\x10\n\x0cNO_INTERFACE\x10\x04\x12\x12\n\x0eMAX_RETRANSMIT\x10\x05\x12\x0e\n\nNO_CHANNEL\x10\x06\x12\r\n\tTOO_LARGE\x10\x07\x12\x0f\n\x0bNO_RESPONSE\x10\x08\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10 \x12\x12\n\x0eNOT_AUTHORIZED\x10!B\t\n\x07variant\"{\n\x04\x44\x61ta\x12\x19\n\x07portnum\x18\x01 \x01(\x0e\x32\x08.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x12\x15\n\rwant_response\x18\x03 \x01(\x08\x12\x0c\n\x04\x64\x65st\x18\x04 \x01(\x07\x12\x0e\n\x06source\x18\x05 \x01(\x07\x12\x12\n\nrequest_id\x18\x06 \x01(\x07\"\xe0\x02\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\x07\x12\n\n\x02to\x18\x02 \x01(\x07\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\r\x12\x18\n\x07\x64\x65\x63oded\x18\x04 \x01(\x0b\x32\x05.DataH\x00\x12\x13\n\tencrypted\x18\x05 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\x07\x12\x0f\n\x07rx_time\x18\x07 \x01(\x07\x12\x0e\n\x06rx_snr\x18\x08 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x12&\n\x08priority\x18\x0c \x01(\x0e\x32\x14.MeshPacket.Priority\x12\x0f\n\x07rx_rssi\x18\r \x01(\x05\"[\n\x08Priority\x12\t\n\x05UNSET\x10\x00\x12\x07\n\x03MIN\x10\x01\x12\x0e\n\nBACKGROUND\x10\n\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10@\x12\x0c\n\x08RELIABLE\x10\x46\x12\x07\n\x03\x41\x43K\x10x\x12\x07\n\x03MAX\x10\x7f\x42\x10\n\x0epayloadVariant\"j\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\x12\n\nlast_heard\x18\x04 \x01(\x07\"\xcb\x02\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x11\n\tnum_bands\x18\x03 \x01(\r\x12\x14\n\x0cmax_channels\x18\x0f \x01(\r\x12\x12\n\x06region\x18\x04 \x01(\tB\x02\x18\x01\x12\x1f\n\x13hw_model_deprecated\x18\x05 \x01(\tB\x02\x18\x01\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12&\n\nerror_code\x18\x07 \x01(\x0e\x32\x12.CriticalErrorCode\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x14\n\x0creboot_count\x18\n \x01(\r\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\"\xb5\x01\n\tLogRecord\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04time\x18\x02 \x01(\x07\x12\x0e\n\x06source\x18\x03 \x01(\t\x12\x1f\n\x05level\x18\x04 \x01(\x0e\x32\x10.LogRecord.Level\"X\n\x05Level\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x43RITICAL\x10\x32\x12\t\n\x05\x45RROR\x10(\x12\x0b\n\x07WARNING\x10\x1e\x12\x08\n\x04INFO\x10\x14\x12\t\n\x05\x44\x45\x42UG\x10\n\x12\t\n\x05TRACE\x10\x05\"\xe9\x01\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x0b \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 \n\nlog_record\x18\x07 \x01(\x0b\x32\n.LogRecordH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x42\x10\n\x0epayloadVariantJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07\"\x82\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12\x14\n\ndisconnect\x18h \x01(\x08H\x00\x42\x10\n\x0epayloadVariantJ\x04\x08\x01\x10\x02J\x04\x08\x65\x10\x66J\x04\x08\x66\x10gJ\x04\x08g\x10h*\xfd\x01\n\rHardwareModel\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08TLORA_V2\x10\x01\x12\x0c\n\x08TLORA_V1\x10\x02\x12\x12\n\x0eTLORA_V2_1_1p6\x10\x03\x12\t\n\x05TBEAM\x10\x04\x12\n\n\x06HELTEC\x10\x05\x12\x0c\n\x08TBEAM0p7\x10\x06\x12\n\n\x06T_ECHO\x10\x07\x12\x10\n\x0cTLORA_V1_1p3\x10\x08\x12\x11\n\rLORA_RELAY_V1\x10 \x12\x0e\n\nNRF52840DK\x10!\x12\x07\n\x03PPR\x10\"\x12\x0f\n\x0bGENIEBLOCKS\x10#\x12\x11\n\rNRF52_UNKNOWN\x10$\x12\r\n\tPORTDUINO\x10%\x12\x0f\n\x0b\x41NDROID_SIM\x10&*.\n\tConstants\x12\n\n\x06Unused\x10\x00\x12\x15\n\x10\x44\x41TA_PAYLOAD_LEN\x10\xf0\x01*\xbd\x01\n\x11\x43riticalErrorCode\x12\x08\n\x04None\x10\x00\x12\x0e\n\nTxWatchdog\x10\x01\x12\x12\n\x0eSleepEnterWait\x10\x02\x12\x0b\n\x07NoRadio\x10\x03\x12\x0f\n\x0bUnspecified\x10\x04\x12\x13\n\x0fUBloxInitFailed\x10\x05\x12\x0c\n\x08NoAXP192\x10\x06\x12\x17\n\x13InvalidRadioSetting\x10\x07\x12\x12\n\x0eTransmitFailed\x10\x08\x12\x0c\n\x08\x42rownout\x10\tB#\n\x13\x63om.geeksville.meshB\nMeshProtosH\x03\x62\x06proto3'
+ serialized_pb=b'\n\nmesh.proto\x1a\x0eportnums.proto\"v\n\x08Position\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\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(\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t\"\x81\x01\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\x12 \n\x08hw_model\x18\x06 \x01(\x0e\x32\x0e.HardwareModel\x12\x13\n\x0bis_licensed\x18\x07 \x01(\x08\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x07\"\xc5\x02\n\x07Routing\x12(\n\rroute_request\x18\x01 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x02 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0c\x65rror_reason\x18\x03 \x01(\x0e\x32\x0e.Routing.ErrorH\x00\"\xb4\x01\n\x05\x45rror\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\x12\x10\n\x0cNO_INTERFACE\x10\x04\x12\x12\n\x0eMAX_RETRANSMIT\x10\x05\x12\x0e\n\nNO_CHANNEL\x10\x06\x12\r\n\tTOO_LARGE\x10\x07\x12\x0f\n\x0bNO_RESPONSE\x10\x08\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10 \x12\x12\n\x0eNOT_AUTHORIZED\x10!B\t\n\x07variant\"{\n\x04\x44\x61ta\x12\x19\n\x07portnum\x18\x01 \x01(\x0e\x32\x08.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x12\x15\n\rwant_response\x18\x03 \x01(\x08\x12\x0c\n\x04\x64\x65st\x18\x04 \x01(\x07\x12\x0e\n\x06source\x18\x05 \x01(\x07\x12\x12\n\nrequest_id\x18\x06 \x01(\x07\"\xe0\x02\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\x07\x12\n\n\x02to\x18\x02 \x01(\x07\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\r\x12\x18\n\x07\x64\x65\x63oded\x18\x04 \x01(\x0b\x32\x05.DataH\x00\x12\x13\n\tencrypted\x18\x05 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\x07\x12\x0f\n\x07rx_time\x18\x07 \x01(\x07\x12\x0e\n\x06rx_snr\x18\x08 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x12&\n\x08priority\x18\x0c \x01(\x0e\x32\x14.MeshPacket.Priority\x12\x0f\n\x07rx_rssi\x18\r \x01(\x05\"[\n\x08Priority\x12\t\n\x05UNSET\x10\x00\x12\x07\n\x03MIN\x10\x01\x12\x0e\n\nBACKGROUND\x10\n\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10@\x12\x0c\n\x08RELIABLE\x10\x46\x12\x07\n\x03\x41\x43K\x10x\x12\x07\n\x03MAX\x10\x7f\x42\x10\n\x0epayloadVariant\"j\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\x12\n\nlast_heard\x18\x04 \x01(\x07\"\xcb\x02\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x11\n\tnum_bands\x18\x03 \x01(\r\x12\x14\n\x0cmax_channels\x18\x0f \x01(\r\x12\x12\n\x06region\x18\x04 \x01(\tB\x02\x18\x01\x12\x1f\n\x13hw_model_deprecated\x18\x05 \x01(\tB\x02\x18\x01\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12&\n\nerror_code\x18\x07 \x01(\x0e\x32\x12.CriticalErrorCode\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x14\n\x0creboot_count\x18\n \x01(\r\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\"\xb5\x01\n\tLogRecord\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04time\x18\x02 \x01(\x07\x12\x0e\n\x06source\x18\x03 \x01(\t\x12\x1f\n\x05level\x18\x04 \x01(\x0e\x32\x10.LogRecord.Level\"X\n\x05Level\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x43RITICAL\x10\x32\x12\t\n\x05\x45RROR\x10(\x12\x0b\n\x07WARNING\x10\x1e\x12\x08\n\x04INFO\x10\x14\x12\t\n\x05\x44\x45\x42UG\x10\n\x12\t\n\x05TRACE\x10\x05\"\xe9\x01\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x0b \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 \n\nlog_record\x18\x07 \x01(\x0b\x32\n.LogRecordH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x42\x10\n\x0epayloadVariantJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07\"\xe1\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12&\n\tpeer_info\x18\x03 \x01(\x0b\x32\x11.ToRadio.PeerInfoH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12\x14\n\ndisconnect\x18h \x01(\x08H\x00\x1a\x35\n\x08PeerInfo\x12\x13\n\x0b\x61pp_version\x18\x01 \x01(\r\x12\x14\n\x0cmqtt_gateway\x18\x02 \x01(\x08\x42\x10\n\x0epayloadVariantJ\x04\x08\x01\x10\x02J\x04\x08\x65\x10\x66J\x04\x08\x66\x10gJ\x04\x08g\x10h*\x8a\x02\n\rHardwareModel\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08TLORA_V2\x10\x01\x12\x0c\n\x08TLORA_V1\x10\x02\x12\x12\n\x0eTLORA_V2_1_1p6\x10\x03\x12\t\n\x05TBEAM\x10\x04\x12\n\n\x06HELTEC\x10\x05\x12\x0c\n\x08TBEAM0p7\x10\x06\x12\n\n\x06T_ECHO\x10\x07\x12\x10\n\x0cTLORA_V1_1p3\x10\x08\x12\x0b\n\x07RAK4631\x10\t\x12\x11\n\rLORA_RELAY_V1\x10 \x12\x0e\n\nNRF52840DK\x10!\x12\x07\n\x03PPR\x10\"\x12\x0f\n\x0bGENIEBLOCKS\x10#\x12\x11\n\rNRF52_UNKNOWN\x10$\x12\r\n\tPORTDUINO\x10%\x12\x0f\n\x0b\x41NDROID_SIM\x10&*.\n\tConstants\x12\n\n\x06Unused\x10\x00\x12\x15\n\x10\x44\x41TA_PAYLOAD_LEN\x10\xf0\x01*\xbd\x01\n\x11\x43riticalErrorCode\x12\x08\n\x04None\x10\x00\x12\x0e\n\nTxWatchdog\x10\x01\x12\x12\n\x0eSleepEnterWait\x10\x02\x12\x0b\n\x07NoRadio\x10\x03\x12\x0f\n\x0bUnspecified\x10\x04\x12\x13\n\x0fUBloxInitFailed\x10\x05\x12\x0c\n\x08NoAXP192\x10\x06\x12\x17\n\x13InvalidRadioSetting\x10\x07\x12\x12\n\x0eTransmitFailed\x10\x08\x12\x0c\n\x08\x42rownout\x10\tB#\n\x13\x63om.geeksville.meshB\nMeshProtosH\x03\x62\x06proto3'
,
dependencies=[portnums__pb2.DESCRIPTOR,])
@@ -107,45 +107,50 @@ _HARDWAREMODEL = _descriptor.EnumDescriptor(
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='LORA_RELAY_V1', index=9, number=32,
+ name='RAK4631', index=9, number=9,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='NRF52840DK', index=10, number=33,
+ name='LORA_RELAY_V1', index=10, number=32,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='PPR', index=11, number=34,
+ name='NRF52840DK', index=11, number=33,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='GENIEBLOCKS', index=12, number=35,
+ name='PPR', index=12, number=34,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='NRF52_UNKNOWN', index=13, number=36,
+ name='GENIEBLOCKS', index=13, number=35,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='PORTDUINO', index=14, number=37,
+ name='NRF52_UNKNOWN', index=14, number=36,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
- name='ANDROID_SIM', index=15, number=38,
+ name='PORTDUINO', index=15, number=37,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key),
+ _descriptor.EnumValueDescriptor(
+ name='ANDROID_SIM', index=16, number=38,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
],
containing_type=None,
serialized_options=None,
- serialized_start=2119,
- serialized_end=2372,
+ serialized_start=2214,
+ serialized_end=2480,
)
_sym_db.RegisterEnumDescriptor(_HARDWAREMODEL)
@@ -170,8 +175,8 @@ _CONSTANTS = _descriptor.EnumDescriptor(
],
containing_type=None,
serialized_options=None,
- serialized_start=2374,
- serialized_end=2420,
+ serialized_start=2482,
+ serialized_end=2528,
)
_sym_db.RegisterEnumDescriptor(_CONSTANTS)
@@ -236,8 +241,8 @@ _CRITICALERRORCODE = _descriptor.EnumDescriptor(
],
containing_type=None,
serialized_options=None,
- serialized_start=2423,
- serialized_end=2612,
+ serialized_start=2531,
+ serialized_end=2720,
)
_sym_db.RegisterEnumDescriptor(_CRITICALERRORCODE)
@@ -251,6 +256,7 @@ HELTEC = 5
TBEAM0p7 = 6
T_ECHO = 7
TLORA_V1_1p3 = 8
+RAK4631 = 9
LORA_RELAY_V1 = 32
NRF52840DK = 33
PPR = 34
@@ -1145,6 +1151,44 @@ _FROMRADIO = _descriptor.Descriptor(
)
+_TORADIO_PEERINFO = _descriptor.Descriptor(
+ name='PeerInfo',
+ full_name='ToRadio.PeerInfo',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='app_version', full_name='ToRadio.PeerInfo.app_version', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ _descriptor.FieldDescriptor(
+ name='mqtt_gateway', full_name='ToRadio.PeerInfo.mqtt_gateway', index=1,
+ number=2, 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, create_key=_descriptor._internal_create_key),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2116,
+ serialized_end=2169,
+)
+
_TORADIO = _descriptor.Descriptor(
name='ToRadio',
full_name='ToRadio',
@@ -1161,14 +1205,21 @@ _TORADIO = _descriptor.Descriptor(
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
- name='want_config_id', full_name='ToRadio.want_config_id', index=1,
+ name='peer_info', full_name='ToRadio.peer_info', index=1,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ _descriptor.FieldDescriptor(
+ name='want_config_id', full_name='ToRadio.want_config_id', index=2,
number=100, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
- name='disconnect', full_name='ToRadio.disconnect', index=2,
+ name='disconnect', full_name='ToRadio.disconnect', index=3,
number=104, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
@@ -1177,7 +1228,7 @@ _TORADIO = _descriptor.Descriptor(
],
extensions=[
],
- nested_types=[],
+ nested_types=[_TORADIO_PEERINFO, ],
enum_types=[
],
serialized_options=None,
@@ -1192,7 +1243,7 @@ _TORADIO = _descriptor.Descriptor(
fields=[]),
],
serialized_start=1986,
- serialized_end=2116,
+ serialized_end=2211,
)
_USER.fields_by_name['hw_model'].enum_type = _HARDWAREMODEL
@@ -1246,10 +1297,15 @@ _FROMRADIO.fields_by_name['config_complete_id'].containing_oneof = _FROM
_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
_FROMRADIO.fields_by_name['rebooted'])
_FROMRADIO.fields_by_name['rebooted'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
+_TORADIO_PEERINFO.containing_type = _TORADIO
_TORADIO.fields_by_name['packet'].message_type = _MESHPACKET
+_TORADIO.fields_by_name['peer_info'].message_type = _TORADIO_PEERINFO
_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
_TORADIO.fields_by_name['packet'])
_TORADIO.fields_by_name['packet'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
+_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
+ _TORADIO.fields_by_name['peer_info'])
+_TORADIO.fields_by_name['peer_info'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
_TORADIO.fields_by_name['want_config_id'])
_TORADIO.fields_by_name['want_config_id'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
@@ -1343,11 +1399,19 @@ FromRadio = _reflection.GeneratedProtocolMessageType('FromRadio', (_mess
_sym_db.RegisterMessage(FromRadio)
ToRadio = _reflection.GeneratedProtocolMessageType('ToRadio', (_message.Message,), {
+
+ 'PeerInfo' : _reflection.GeneratedProtocolMessageType('PeerInfo', (_message.Message,), {
+ 'DESCRIPTOR' : _TORADIO_PEERINFO,
+ '__module__' : 'mesh_pb2'
+ # @@protoc_insertion_point(class_scope:ToRadio.PeerInfo)
+ })
+ ,
'DESCRIPTOR' : _TORADIO,
'__module__' : 'mesh_pb2'
# @@protoc_insertion_point(class_scope:ToRadio)
})
_sym_db.RegisterMessage(ToRadio)
+_sym_db.RegisterMessage(ToRadio.PeerInfo)
DESCRIPTOR._options = None
@@ -1916,6 +1980,10 @@ _MYNODEINFO.fields_by_name['hw_model_deprecated']._options = None
+var PeerInfo
+
+A ProtocolMessage
+
Instance variables
@@ -1927,6 +1995,10 @@ _MYNODEINFO.fields_by_name['hw_model_deprecated']._options = None
-
Field ToRadio.packet
+var peer_info
+-
+
Field ToRadio.peer_info
+
var want_config_id
-
Field ToRadio.want_config_id
@@ -2135,10 +2207,12 @@ _MYNODEINFO.fields_by_name['hw_model_deprecated']._options = None
-
ToRadio
-
diff --git a/docs/meshtastic/test.html b/docs/meshtastic/test.html
index 653ca1b..d6ee1f1 100644
--- a/docs/meshtastic/test.html
+++ b/docs/meshtastic/test.html
@@ -32,7 +32,7 @@ from . import SerialInterface, TCPInterface, BROADCAST_NUM
from pubsub import pub
import time
import sys
-import threading
+import threading, traceback
from dotmap import DotMap
"""The interfaces we are using for our tests"""
@@ -195,13 +195,18 @@ def testSimulator():
"""
logging.basicConfig(level=logging.DEBUG if False else logging.INFO)
logging.info("Connecting to simulator on localhost!")
- iface = TCPInterface("localhost")
- iface.showInfo()
- iface.localNode.showInfo()
- iface.localNode.exitSimulator()
- iface.close()
- logging.info("Integration test successful!")
- sys.exit(0)
+ try:
+ iface = TCPInterface("localhost")
+ iface.showInfo()
+ iface.localNode.showInfo()
+ iface.localNode.exitSimulator()
+ iface.close()
+ logging.info("Integration test successful!")
+ sys.exit(0)
+ except:
+ print("Error while testing simulator:", sys.exc_info()[0])
+ traceback.print_exc()
+ sys.exit(1)
diff --git a/setup.py b/setup.py
index bf99f45..23e7043 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.2.25",
+ version="1.2.29",
description="Python API & client shell for talking to Meshtastic devices",
long_description=long_description,
long_description_content_type="text/markdown",