mirror of
https://github.com/meshtastic/python.git
synced 2025-12-26 01:17:51 -05:00
Compare commits
238 Commits
2.4.3
...
backup-com
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7422d9d314 | ||
|
|
5ee0264737 | ||
|
|
ec13bd308a | ||
|
|
2d88d8e918 | ||
|
|
fb48fc20b3 | ||
|
|
336e5154a3 | ||
|
|
3008e039fb | ||
|
|
4bf61d4c98 | ||
|
|
faa8064ccc | ||
|
|
2f44351945 | ||
|
|
852949575b | ||
|
|
e2c9c1315e | ||
|
|
f41ef042a9 | ||
|
|
84bec5a7c4 | ||
|
|
985366c812 | ||
|
|
3954fbd404 | ||
|
|
5f174b2850 | ||
|
|
23ea19c00b | ||
|
|
acc47146c9 | ||
|
|
dd8803793d | ||
|
|
68ec588804 | ||
|
|
2f48594dc3 | ||
|
|
c7c3c69fc3 | ||
|
|
53e40d5aab | ||
|
|
dd3da6a670 | ||
|
|
e500b399f4 | ||
|
|
27ac28e300 | ||
|
|
6bc5f5e305 | ||
|
|
c844e4e0fe | ||
|
|
060df86bb6 | ||
|
|
7d87d5037e | ||
|
|
4ec7698d94 | ||
|
|
7cc65aa08a | ||
|
|
cc411ce0bb | ||
|
|
edff956f9d | ||
|
|
bd68739158 | ||
|
|
530d92ead2 | ||
|
|
60f9dc6266 | ||
|
|
f9ae021e43 | ||
|
|
317d81c983 | ||
|
|
5837bd0172 | ||
|
|
5487f7a791 | ||
|
|
c6d8a540eb | ||
|
|
0962c9b058 | ||
|
|
4f98602ac2 | ||
|
|
6ebddb67c0 | ||
|
|
82554a1f18 | ||
|
|
8c115dc636 | ||
|
|
e2fe359527 | ||
|
|
5600ce92b0 | ||
|
|
efb848adf9 | ||
|
|
0d8646189f | ||
|
|
d0023df8ca | ||
|
|
b522abf33e | ||
|
|
c086b6372e | ||
|
|
6ec506fe3b | ||
|
|
fc3b81dfde | ||
|
|
9c53ea017c | ||
|
|
1e6625d062 | ||
|
|
0487ce5e1a | ||
|
|
aac19b2ecc | ||
|
|
0fb72b8ad1 | ||
|
|
872fbef5d6 | ||
|
|
ec4fbe3a59 | ||
|
|
6bab385380 | ||
|
|
b8178d513a | ||
|
|
f4c085fc50 | ||
|
|
57f0598082 | ||
|
|
55d3188408 | ||
|
|
7b64fbb71b | ||
|
|
7f85eb0285 | ||
|
|
d05ef17ab3 | ||
|
|
d161291ca4 | ||
|
|
4e267c75b0 | ||
|
|
f56b9eefa6 | ||
|
|
2de1f1921c | ||
|
|
227507780e | ||
|
|
9f286c9023 | ||
|
|
0b1545393e | ||
|
|
245a9e40b1 | ||
|
|
749c6a70bc | ||
|
|
afd071c24e | ||
|
|
29f355bd61 | ||
|
|
4b6d7a8587 | ||
|
|
7cc18e9df6 | ||
|
|
a765bccf4d | ||
|
|
f950ecae2d | ||
|
|
7c7170a5dd | ||
|
|
df191e149b | ||
|
|
843abe587f | ||
|
|
ff7dcc3afb | ||
|
|
d66b8fa9dd | ||
|
|
f6f8ccfcbc | ||
|
|
cace959ca4 | ||
|
|
01ffd83d64 | ||
|
|
9284a848f2 | ||
|
|
18ac0d6d5c | ||
|
|
7c89e231bd | ||
|
|
4673824236 | ||
|
|
d87eddfd33 | ||
|
|
31f322f1c2 | ||
|
|
89b41c1a19 | ||
|
|
1a5ca789c2 | ||
|
|
74c911cb75 | ||
|
|
579383cd5a | ||
|
|
03ac322583 | ||
|
|
c63814358a | ||
|
|
663fabce74 | ||
|
|
6243965044 | ||
|
|
b180b6fb15 | ||
|
|
7bb8e4e9dd | ||
|
|
4c7ac60be6 | ||
|
|
0b086d10f8 | ||
|
|
426795fccd | ||
|
|
fb88ee114c | ||
|
|
a4630b53eb | ||
|
|
646aa981d5 | ||
|
|
9381acd6ac | ||
|
|
384063db19 | ||
|
|
20d75d9023 | ||
|
|
0deb1d788f | ||
|
|
1070d9202b | ||
|
|
b90de8b73b | ||
|
|
2e79ecf759 | ||
|
|
578d3e4b24 | ||
|
|
4ca13bcede | ||
|
|
6ceae7c72f | ||
|
|
4c29d7dd0f | ||
|
|
839bbbcad2 | ||
|
|
1abb9fb213 | ||
|
|
7fcbbe9b80 | ||
|
|
073274cb00 | ||
|
|
92a3986a8f | ||
|
|
f08ec1885b | ||
|
|
feca49faed | ||
|
|
dfaf1a275d | ||
|
|
da7fa31805 | ||
|
|
12fd29b203 | ||
|
|
a43dd201ba | ||
|
|
a64a9d203a | ||
|
|
10136962d7 | ||
|
|
3afb294f9b | ||
|
|
ee405fec41 | ||
|
|
3eabaf91d0 | ||
|
|
78b92cecc9 | ||
|
|
7088b90514 | ||
|
|
2ae81f8602 | ||
|
|
923f5e82d0 | ||
|
|
05731128fa | ||
|
|
0523d4c94f | ||
|
|
90e901de79 | ||
|
|
6606851135 | ||
|
|
33fecbd74d | ||
|
|
6b9db7abd9 | ||
|
|
ece6286d82 | ||
|
|
e335f12a3b | ||
|
|
0da405168f | ||
|
|
58d9039a04 | ||
|
|
f77e788aa8 | ||
|
|
aba381fb54 | ||
|
|
0bb4b31b6a | ||
|
|
915066e0af | ||
|
|
6be3969577 | ||
|
|
b73cc1f499 | ||
|
|
65305af184 | ||
|
|
3fb1e67357 | ||
|
|
cbd3c119fe | ||
|
|
bbd6d6a541 | ||
|
|
6e1217c7ca | ||
|
|
81db38956b | ||
|
|
27729995d2 | ||
|
|
d875a574b6 | ||
|
|
40019a9712 | ||
|
|
de657bab24 | ||
|
|
40353a387e | ||
|
|
9949d144a1 | ||
|
|
48a06c6e1e | ||
|
|
c696d59b90 | ||
|
|
4fdbcb9679 | ||
|
|
5d6dfb877b | ||
|
|
951edfe27b | ||
|
|
5cc9627e21 | ||
|
|
bf904c6906 | ||
|
|
2026212a00 | ||
|
|
34f9be255e | ||
|
|
e561222ea7 | ||
|
|
73a1bbc7d5 | ||
|
|
8f2c397fbf | ||
|
|
62f5201a38 | ||
|
|
9e7d5e96ab | ||
|
|
aa74db46cb | ||
|
|
1967519deb | ||
|
|
662aea049a | ||
|
|
44cfd72a80 | ||
|
|
abe1dd47ca | ||
|
|
584a14f578 | ||
|
|
f7724295f9 | ||
|
|
cc2067b729 | ||
|
|
180ddbcd1a | ||
|
|
3bbd02c915 | ||
|
|
23e6eca056 | ||
|
|
21ff4a1a4a | ||
|
|
ef6db0e48c | ||
|
|
43b0993aaa | ||
|
|
8ba92da7cf | ||
|
|
0d26c26f7e | ||
|
|
399dd477b8 | ||
|
|
3811226a61 | ||
|
|
b6547c9737 | ||
|
|
9612aea9b9 | ||
|
|
4b60c5b457 | ||
|
|
c92474cf36 | ||
|
|
b2acc84717 | ||
|
|
1981f0e899 | ||
|
|
84dff75399 | ||
|
|
df12b8a659 | ||
|
|
eedf42b904 | ||
|
|
e7ed254d9d | ||
|
|
dfa29bbb7c | ||
|
|
5a06888cc7 | ||
|
|
a9e2168f1d | ||
|
|
eec745c861 | ||
|
|
4cc283d004 | ||
|
|
bc508ff9e6 | ||
|
|
ff72fc4804 | ||
|
|
78399503c5 | ||
|
|
216fd7ddc4 | ||
|
|
688693d2fb | ||
|
|
15b5e93563 | ||
|
|
1bbcc452ae | ||
|
|
1abe00d0b2 | ||
|
|
c8cf8094c3 | ||
|
|
477690edde | ||
|
|
58466f2ab7 | ||
|
|
bb6f51eb43 | ||
|
|
48987c38e2 | ||
|
|
60de9dddb1 | ||
|
|
a29ee840f2 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -2,3 +2,4 @@
|
||||
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||
*.{sh,[sS][hH]} text eol=lf
|
||||
meshtastic/protobuf/* linguist-generated=true
|
||||
|
||||
17
.vscode/launch.json
vendored
17
.vscode/launch.json
vendored
@@ -245,6 +245,23 @@
|
||||
"module": "meshtastic",
|
||||
"justMyCode": true,
|
||||
"args": ["--debug", "--nodes"]
|
||||
},
|
||||
{
|
||||
"name": "meshtastic nodes table",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"module": "meshtastic",
|
||||
"justMyCode": true,
|
||||
"args": ["--nodes"]
|
||||
},
|
||||
{
|
||||
"name": "meshtastic nodes table with show-fields",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"module": "meshtastic",
|
||||
"justMyCode": true,
|
||||
"args": ["--nodes", "--show-fields", "AKA,Pubkey,Role,Role,Role,Latitude,Latitude,deviceMetrics.voltage"]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ Events are delivered using a publish-subscribe model, and you can subscribe to o
|
||||
|
||||
**[Getting Started Guide](https://meshtastic.org/docs/software/python/cli/installation)**
|
||||
|
||||
(Documentation/API Reference is currently offline)
|
||||
**[API Documentation](https://python.meshtastic.org)**
|
||||
|
||||
## Call for Contributors
|
||||
|
||||
|
||||
55
examples/waypoint.py
Normal file
55
examples/waypoint.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""Program to create and delete waypoint
|
||||
To run:
|
||||
python3 examples/waypoint.py --port /dev/ttyUSB0 create 45 test the_desc_2 '2024-12-18T23:05:23' 48.74 7.35
|
||||
python3 examples/waypoint.py delete 45
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
import meshtastic
|
||||
import meshtastic.serial_interface
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='waypoint',
|
||||
description='Create and delete Meshtastic waypoint')
|
||||
parser.add_argument('--port', default=None)
|
||||
parser.add_argument('--debug', default=False, action='store_true')
|
||||
|
||||
subparsers = parser.add_subparsers(dest='cmd')
|
||||
parser_delete = subparsers.add_parser('delete', help='Delete a waypoint')
|
||||
parser_delete.add_argument('id', help="id of the waypoint")
|
||||
|
||||
parser_create = subparsers.add_parser('create', help='Create a new waypoint')
|
||||
parser_create.add_argument('id', help="id of the waypoint")
|
||||
parser_create.add_argument('name', help="name of the waypoint")
|
||||
parser_create.add_argument('description', help="description of the waypoint")
|
||||
parser_create.add_argument('expire', help="expiration date of the waypoint as interpreted by datetime.fromisoformat")
|
||||
parser_create.add_argument('latitude', help="latitude of the waypoint")
|
||||
parser_create.add_argument('longitude', help="longitude of the waypoint")
|
||||
|
||||
args = parser.parse_args()
|
||||
print(args)
|
||||
|
||||
# By default will try to find a meshtastic device,
|
||||
# otherwise provide a device path like /dev/ttyUSB0
|
||||
if args.debug:
|
||||
d = sys.stderr
|
||||
else:
|
||||
d = None
|
||||
with meshtastic.serial_interface.SerialInterface(args.port, debugOut=d) as iface:
|
||||
if args.cmd == 'create':
|
||||
p = iface.sendWaypoint(
|
||||
waypoint_id=int(args.id),
|
||||
name=args.name,
|
||||
description=args.description,
|
||||
expire=int(datetime.datetime.fromisoformat(args.expire).timestamp()),
|
||||
latitude=float(args.latitude),
|
||||
longitude=float(args.longitude),
|
||||
)
|
||||
else:
|
||||
p = iface.deleteWaypoint(int(args.id))
|
||||
print(p)
|
||||
|
||||
# iface.close()
|
||||
@@ -2,41 +2,44 @@
|
||||
# A library for the Meshtastic Client API
|
||||
|
||||
Primary interfaces: SerialInterface, TCPInterface, BLEInterface
|
||||
|
||||
Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
|
||||
|
||||
Source code on [github](https://github.com/meshtastic/python)
|
||||
|
||||
notable properties of interface classes:
|
||||
|
||||
- nodes - The database of received nodes. Includes always up-to-date location and username information for each
|
||||
- `nodes` - The database of received nodes. Includes always up-to-date location and username information for each
|
||||
node in the mesh. This is a read-only datastructure.
|
||||
- nodesByNum - like "nodes" but keyed by nodeNum instead of nodeId
|
||||
- myInfo & metadata - Contain read-only information about the local radio device (software version, hardware version, etc)
|
||||
- localNode - Pointer to a node object for the local node
|
||||
- `nodesByNum` - like "nodes" but keyed by nodeNum instead of nodeId. As such, includes "unknown" nodes which haven't seen a User packet yet
|
||||
- `myInfo` & `metadata` - Contain read-only information about the local radio device (software version, hardware version, etc)
|
||||
- `localNode` - Pointer to a node object for the local node
|
||||
|
||||
notable properties of nodes:
|
||||
- localConfig - Current radio settings, can be written to the radio with the `writeConfig` method.
|
||||
- moduleConfig - Current module settings, can be written to the radio with the `writeConfig` method.
|
||||
- channels - The node's channels, keyed by index.
|
||||
|
||||
- `localConfig` - Current radio settings, can be written to the radio with the `writeConfig` method.
|
||||
- `moduleConfig` - Current module settings, can be written to the radio with the `writeConfig` method.
|
||||
- `channels` - The node's channels, keyed by index.
|
||||
|
||||
# Published PubSub topics
|
||||
|
||||
We use a [publish-subscribe](https://pypubsub.readthedocs.io/en/v4.0.3/) model to communicate asynchronous events. Available
|
||||
topics:
|
||||
|
||||
- meshtastic.connection.established - published once we've successfully connected to the radio and downloaded the node DB
|
||||
- meshtastic.connection.lost - published once we've lost our link to the radio
|
||||
- meshtastic.receive.text(packet) - delivers a received packet as a dictionary, if you only care about a particular
|
||||
- `meshtastic.connection.established` - published once we've successfully connected to the radio and downloaded the node DB
|
||||
- `meshtastic.connection.lost` - published once we've lost our link to the radio
|
||||
- `meshtastic.receive.text(packet)` - delivers a received packet as a dictionary, if you only care about a particular
|
||||
type of packet, you should subscribe to the full topic name. If you want to see all packets, simply subscribe to "meshtastic.receive".
|
||||
- meshtastic.receive.position(packet)
|
||||
- meshtastic.receive.user(packet)
|
||||
- meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum)
|
||||
- meshtastic.node.updated(node = NodeInfo) - published when a node in the DB changes (appears, location changed, username changed, etc...)
|
||||
- meshtastic.log.line(line) - a raw unparsed log line from the radio
|
||||
- `meshtastic.receive.position(packet)`
|
||||
- `meshtastic.receive.user(packet)`
|
||||
- `meshtastic.receive.data.portnum(packet)` (where portnum is an integer or well known PortNum enum)
|
||||
- `meshtastic.node.updated(node = NodeInfo)` - published when a node in the DB changes (appears, location changed, username changed, etc...)
|
||||
- `meshtastic.log.line(line)` - a raw unparsed log line from the radio
|
||||
|
||||
We receive position, user, or data packets from the mesh. You probably only care about meshtastic.receive.data. The first argument for
|
||||
that publish will be the packet. Text or binary data packets (from sendData or sendText) will both arrive this way. If you print packet
|
||||
you'll see the fields in the dictionary. decoded.data.payload will contain the raw bytes that were sent. If the packet was sent with
|
||||
sendText, decoded.data.text will **also** be populated with the decoded string. For ASCII these two strings will be the same, but for
|
||||
We receive position, user, or data packets from the mesh. You probably only care about `meshtastic.receive.data`. The first argument for
|
||||
that publish will be the packet. Text or binary data packets (from `sendData` or `sendText`) will both arrive this way. If you print packet
|
||||
you'll see the fields in the dictionary. `decoded.data.payload` will contain the raw bytes that were sent. If the packet was sent with
|
||||
`sendText`, `decoded.data.text` will **also** be populated with the decoded string. For ASCII these two strings will be the same, but for
|
||||
unicode scripts they can be different.
|
||||
|
||||
# Example Usage
|
||||
@@ -77,7 +80,6 @@ from typing import *
|
||||
|
||||
import google.protobuf.json_format
|
||||
import serial # type: ignore[import-untyped]
|
||||
from dotmap import DotMap # type: ignore[import-untyped]
|
||||
from google.protobuf.json_format import MessageToJson
|
||||
from pubsub import pub # type: ignore[import-untyped]
|
||||
from tabulate import tabulate
|
||||
@@ -108,13 +110,13 @@ from . import (
|
||||
LOCAL_ADDR = "^local"
|
||||
"""A special ID that means the local node"""
|
||||
|
||||
BROADCAST_NUM = 0xFFFFFFFF
|
||||
BROADCAST_NUM: int = 0xFFFFFFFF
|
||||
"""if using 8 bit nodenums this will be shortened on the target"""
|
||||
|
||||
BROADCAST_ADDR = "^all"
|
||||
"""A special ID that means broadcast"""
|
||||
|
||||
OUR_APP_VERSION = 20300
|
||||
OUR_APP_VERSION: int = 20300
|
||||
"""The numeric buildnumber (shared with android apps) specifying the
|
||||
level of device code we are guaranteed to understand
|
||||
|
||||
@@ -131,7 +133,9 @@ class ResponseHandler(NamedTuple):
|
||||
"""A pending response callback, waiting for a response to one of our messages"""
|
||||
|
||||
# requestId: int - used only as a key
|
||||
#: a callable to call when a response is received
|
||||
callback: Callable
|
||||
#: Whether ACKs and NAKs should be passed to this handler
|
||||
ackPermitted: bool = False
|
||||
# FIXME, add timestamp and age out old requests
|
||||
|
||||
@@ -139,11 +143,11 @@ class ResponseHandler(NamedTuple):
|
||||
class KnownProtocol(NamedTuple):
|
||||
"""Used to automatically decode known protocol payloads"""
|
||||
|
||||
#: A descriptive name (e.g. "text", "user", "admin")
|
||||
name: str
|
||||
# portnum: int, now a key
|
||||
# If set, will be called to prase as a protocol buffer
|
||||
#: If set, will be called to parse as a protocol buffer
|
||||
protobufFactory: Optional[Callable] = None
|
||||
# If set, invoked as onReceive(interface, packet)
|
||||
#: If set, invoked as onReceive(interface, packet)
|
||||
onReceive: Optional[Callable] = None
|
||||
|
||||
|
||||
@@ -194,13 +198,31 @@ def _onNodeInfoReceive(iface, asDict):
|
||||
def _onTelemetryReceive(iface, asDict):
|
||||
"""Automatically update device metrics on received packets"""
|
||||
logging.debug(f"in _onTelemetryReceive() asDict:{asDict}")
|
||||
deviceMetrics = asDict.get("decoded", {}).get("telemetry", {}).get("deviceMetrics")
|
||||
if "from" in asDict and deviceMetrics is not None:
|
||||
node = iface._getOrCreateByNum(asDict["from"])
|
||||
newMetrics = node.get("deviceMetrics", {})
|
||||
newMetrics.update(deviceMetrics)
|
||||
logging.debug(f"updating metrics for {asDict['from']} to {newMetrics}")
|
||||
node["deviceMetrics"] = newMetrics
|
||||
if "from" not in asDict:
|
||||
return
|
||||
|
||||
toUpdate = None
|
||||
|
||||
telemetry = asDict.get("decoded", {}).get("telemetry", {})
|
||||
node = iface._getOrCreateByNum(asDict["from"])
|
||||
if "deviceMetrics" in telemetry:
|
||||
toUpdate = "deviceMetrics"
|
||||
elif "environmentMetrics" in telemetry:
|
||||
toUpdate = "environmentMetrics"
|
||||
elif "airQualityMetrics" in telemetry:
|
||||
toUpdate = "airQualityMetrics"
|
||||
elif "powerMetrics" in telemetry:
|
||||
toUpdate = "powerMetrics"
|
||||
elif "localStats" in telemetry:
|
||||
toUpdate = "localStats"
|
||||
else:
|
||||
return
|
||||
|
||||
updateObj = telemetry.get(toUpdate)
|
||||
newMetrics = node.get(toUpdate, {})
|
||||
newMetrics.update(updateObj)
|
||||
logging.debug(f"updating {toUpdate} metrics for {asDict['from']} to {newMetrics}")
|
||||
node[toUpdate] = newMetrics
|
||||
|
||||
def _receiveInfoUpdate(iface, asDict):
|
||||
if "from" in asDict:
|
||||
@@ -209,6 +231,12 @@ def _receiveInfoUpdate(iface, asDict):
|
||||
iface._getOrCreateByNum(asDict["from"])["snr"] = asDict.get("rxSnr")
|
||||
iface._getOrCreateByNum(asDict["from"])["hopLimit"] = asDict.get("hopLimit")
|
||||
|
||||
def _onAdminReceive(iface, asDict):
|
||||
"""Special auto parsing for received messages"""
|
||||
logging.debug(f"in _onAdminReceive() asDict:{asDict}")
|
||||
if "decoded" in asDict and "from" in asDict and "admin" in asDict["decoded"]:
|
||||
adminMessage = asDict["decoded"]["admin"]["raw"]
|
||||
iface._getOrCreateByNum(asDict["from"])["adminSessionPassKey"] = adminMessage.session_passkey
|
||||
|
||||
"""Well known message payloads can register decoders for automatic protobuf parsing"""
|
||||
protocols = {
|
||||
@@ -228,7 +256,9 @@ protocols = {
|
||||
portnums_pb2.PortNum.NODEINFO_APP: KnownProtocol(
|
||||
"user", mesh_pb2.User, _onNodeInfoReceive
|
||||
),
|
||||
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
|
||||
portnums_pb2.PortNum.ADMIN_APP: KnownProtocol(
|
||||
"admin", admin_pb2.AdminMessage, _onAdminReceive
|
||||
),
|
||||
portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
|
||||
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol(
|
||||
"telemetry", telemetry_pb2.Telemetry, _onTelemetryReceive
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ import atexit
|
||||
import logging
|
||||
import struct
|
||||
import time
|
||||
import io
|
||||
from threading import Thread
|
||||
from typing import List, Optional
|
||||
|
||||
@@ -34,9 +35,9 @@ class BLEInterface(MeshInterface):
|
||||
self,
|
||||
address: Optional[str],
|
||||
noProto: bool = False,
|
||||
debugOut=None,
|
||||
debugOut: Optional[io.TextIOWrapper]=None,
|
||||
noNodes: bool = False,
|
||||
):
|
||||
) -> None:
|
||||
MeshInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, noNodes=noNodes
|
||||
)
|
||||
@@ -82,7 +83,7 @@ class BLEInterface(MeshInterface):
|
||||
# Note: the on disconnected callback will call our self.close which will make us nicely wait for threads to exit
|
||||
self._exit_handler = atexit.register(self.client.disconnect)
|
||||
|
||||
def from_num_handler(self, _, b): # pylint: disable=C0116
|
||||
def from_num_handler(self, _, b: bytes) -> None: # pylint: disable=C0116
|
||||
"""Handle callbacks for fromnum notify.
|
||||
Note: this method does not need to be async because it is just setting a bool.
|
||||
"""
|
||||
@@ -150,9 +151,12 @@ class BLEInterface(MeshInterface):
|
||||
)
|
||||
return addressed_devices[0]
|
||||
|
||||
def _sanitize_address(address): # pylint: disable=E0213
|
||||
def _sanitize_address(self, address: Optional[str]) -> Optional[str]: # pylint: disable=E0213
|
||||
"Standardize BLE address by removing extraneous characters and lowercasing."
|
||||
return address.replace("-", "").replace("_", "").replace(":", "").lower()
|
||||
if address is None:
|
||||
return None
|
||||
else:
|
||||
return address.replace("-", "").replace("_", "").replace(":", "").lower()
|
||||
|
||||
def connect(self, address: Optional[str] = None) -> "BLEClient":
|
||||
"Connect to a device by address."
|
||||
@@ -164,12 +168,16 @@ class BLEInterface(MeshInterface):
|
||||
client.discover()
|
||||
return client
|
||||
|
||||
def _receiveFromRadioImpl(self):
|
||||
def _receiveFromRadioImpl(self) -> None:
|
||||
while self._want_receive:
|
||||
if self.should_read:
|
||||
self.should_read = False
|
||||
retries = 0
|
||||
retries: int = 0
|
||||
while self._want_receive:
|
||||
if self.client is None:
|
||||
logging.debug(f"BLE client is None, shutting down")
|
||||
self._want_receive = False
|
||||
continue
|
||||
try:
|
||||
b = bytes(self.client.read_gatt_char(FROMRADIO_UUID))
|
||||
except BleakDBusError as e:
|
||||
@@ -194,8 +202,8 @@ class BLEInterface(MeshInterface):
|
||||
else:
|
||||
time.sleep(0.01)
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
b = toRadio.SerializeToString()
|
||||
def _sendToRadioImpl(self, toRadio) -> None:
|
||||
b: bytes = toRadio.SerializeToString()
|
||||
if b and self.client: # we silently ignore writes while we are shutting down
|
||||
logging.debug(f"TORADIO write: {b.hex()}")
|
||||
try:
|
||||
@@ -211,14 +219,14 @@ class BLEInterface(MeshInterface):
|
||||
time.sleep(0.01)
|
||||
self.should_read = True
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
try:
|
||||
MeshInterface.close(self)
|
||||
except Exception as e:
|
||||
logging.error(f"Error closing mesh interface: {e}")
|
||||
|
||||
if self._want_receive:
|
||||
self.want_receive = False # Tell the thread we want it to stop
|
||||
self._want_receive = False # Tell the thread we want it to stop
|
||||
if self._receiveThread:
|
||||
self._receiveThread.join(
|
||||
timeout=2
|
||||
@@ -230,12 +238,13 @@ class BLEInterface(MeshInterface):
|
||||
self.client.disconnect()
|
||||
self.client.close()
|
||||
self.client = None
|
||||
self._disconnected() # send the disconnected indicator up to clients
|
||||
|
||||
|
||||
class BLEClient:
|
||||
"""Client for managing connection to a BLE device"""
|
||||
|
||||
def __init__(self, address=None, **kwargs):
|
||||
def __init__(self, address=None, **kwargs) -> None:
|
||||
self._eventLoop = asyncio.new_event_loop()
|
||||
self._eventThread = Thread(
|
||||
target=self._run_event_loop, name="BLEClient", daemon=True
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
"""Mesh Interface class
|
||||
"""
|
||||
# pylint: disable=R0917
|
||||
|
||||
import collections
|
||||
import json
|
||||
import logging
|
||||
import math
|
||||
import random
|
||||
import secrets
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import Any, Callable, Dict, List, Optional, Union
|
||||
|
||||
import google.protobuf.json_format
|
||||
import print_color # type: ignore[import-untyped]
|
||||
try:
|
||||
import print_color # type: ignore[import-untyped]
|
||||
except ImportError as e:
|
||||
print_color = None
|
||||
|
||||
from pubsub import pub # type: ignore[import-untyped]
|
||||
from tabulate import tabulate
|
||||
|
||||
@@ -139,19 +147,19 @@ class MeshInterface: # pylint: disable=R0902
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
def __exit__(self, exc_type, exc_value, trace):
|
||||
if exc_type is not None and exc_value is not None:
|
||||
logging.error(
|
||||
f"An exception of type {exc_type} with value {exc_value} has occurred"
|
||||
)
|
||||
if traceback is not None:
|
||||
logging.error(f"Traceback: {traceback}")
|
||||
if trace is not None:
|
||||
logging.error(f"Traceback: {trace}")
|
||||
self.close()
|
||||
|
||||
@staticmethod
|
||||
def _printLogLine(line, interface):
|
||||
"""Print a line of log output."""
|
||||
if interface.debugOut == sys.stdout:
|
||||
if print_color is not None and interface.debugOut == sys.stdout:
|
||||
# this isn't quite correct (could cause false positives), but currently our formatting differs between different log representations
|
||||
if "DEBUG" in line:
|
||||
print_color.print(line, color="cyan", end=None)
|
||||
@@ -214,9 +222,42 @@ class MeshInterface: # pylint: disable=R0902
|
||||
return infos
|
||||
|
||||
def showNodes(
|
||||
self, includeSelf: bool = True
|
||||
self, includeSelf: bool = True, showFields: Optional[List[str]] = None
|
||||
) -> str: # pylint: disable=W0613
|
||||
"""Show table summary of nodes in mesh"""
|
||||
"""Show table summary of nodes in mesh
|
||||
|
||||
Args:
|
||||
includeSelf (bool): Include ourself in the output?
|
||||
showFields (List[str]): List of fields to show in output
|
||||
"""
|
||||
|
||||
def get_human_readable(name):
|
||||
name_map = {
|
||||
"user.longName": "User",
|
||||
"user.id": "ID",
|
||||
"user.shortName": "AKA",
|
||||
"user.hwModel": "Hardware",
|
||||
"user.publicKey": "Pubkey",
|
||||
"user.role": "Role",
|
||||
"position.latitude": "Latitude",
|
||||
"position.longitude": "Longitude",
|
||||
"position.altitude": "Altitude",
|
||||
"deviceMetrics.batteryLevel": "Battery",
|
||||
"deviceMetrics.channelUtilization": "Channel util.",
|
||||
"deviceMetrics.airUtilTx": "Tx air util.",
|
||||
"snr": "SNR",
|
||||
"hopsAway": "Hops",
|
||||
"channel": "Channel",
|
||||
"lastHeard": "LastHeard",
|
||||
"since": "Since",
|
||||
|
||||
}
|
||||
|
||||
if name in name_map:
|
||||
return name_map.get(name) # Default to a formatted guess
|
||||
else:
|
||||
return name
|
||||
|
||||
|
||||
def formatFloat(value, precision=2, unit="") -> Optional[str]:
|
||||
"""Format a float value with precision."""
|
||||
@@ -238,6 +279,29 @@ class MeshInterface: # pylint: disable=R0902
|
||||
return None # not handling a timestamp from the future
|
||||
return _timeago(delta_secs)
|
||||
|
||||
def getNestedValue(node_dict: Dict[str, Any], key_path: str) -> Any:
|
||||
if key_path.index(".") < 0:
|
||||
logging.debug("getNestedValue was called without a nested path.")
|
||||
return None
|
||||
keys = key_path.split(".")
|
||||
value: Optional[Union[str, dict]] = node_dict
|
||||
for key in keys:
|
||||
if isinstance(value, dict):
|
||||
value = value.get(key)
|
||||
else:
|
||||
return None
|
||||
return value
|
||||
|
||||
if showFields is None or len(showFields) == 0:
|
||||
# The default set of fields to show (e.g., the status quo)
|
||||
showFields = ["N", "user.longName", "user.id", "user.shortName", "user.hwModel", "user.publicKey",
|
||||
"user.role", "position.latitude", "position.longitude", "position.altitude",
|
||||
"deviceMetrics.batteryLevel", "deviceMetrics.channelUtilization",
|
||||
"deviceMetrics.airUtilTx", "snr", "hopsAway", "channel", "lastHeard", "since"]
|
||||
else:
|
||||
# Always at least include the row number.
|
||||
showFields.insert(0, "N")
|
||||
|
||||
rows: List[Dict[str, Any]] = []
|
||||
if self.nodesByNum:
|
||||
logging.debug(f"self.nodes:{self.nodes}")
|
||||
@@ -246,64 +310,60 @@ class MeshInterface: # pylint: disable=R0902
|
||||
continue
|
||||
|
||||
presumptive_id = f"!{node['num']:08x}"
|
||||
row = {
|
||||
"N": 0,
|
||||
"User": f"Meshtastic {presumptive_id[-4:]}",
|
||||
"ID": presumptive_id,
|
||||
}
|
||||
|
||||
user = node.get("user")
|
||||
if user:
|
||||
row.update(
|
||||
{
|
||||
"User": user.get("longName", "N/A"),
|
||||
"AKA": user.get("shortName", "N/A"),
|
||||
"ID": user["id"],
|
||||
"Hardware": user.get("hwModel", "UNSET"),
|
||||
}
|
||||
)
|
||||
|
||||
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"),
|
||||
}
|
||||
)
|
||||
|
||||
metrics = node.get("deviceMetrics")
|
||||
if metrics:
|
||||
batteryLevel = metrics.get("batteryLevel")
|
||||
if batteryLevel is not None:
|
||||
if batteryLevel == 0:
|
||||
batteryString = "Powered"
|
||||
# This allows the user to specify fields that wouldn't otherwise be included.
|
||||
fields = {}
|
||||
for field in showFields:
|
||||
if "." in field:
|
||||
raw_value = getNestedValue(node, field)
|
||||
else:
|
||||
# The "since" column is synthesized, it's not retrieved from the device. Get the
|
||||
# lastHeard value here, and then we'll format it properly below.
|
||||
if field == "since":
|
||||
raw_value = node.get("lastHeard")
|
||||
else:
|
||||
batteryString = str(batteryLevel) + "%"
|
||||
row.update({"Battery": batteryString})
|
||||
row.update(
|
||||
{
|
||||
"Channel util.": formatFloat(
|
||||
metrics.get("channelUtilization"), 2, "%"
|
||||
),
|
||||
"Tx air util.": formatFloat(
|
||||
metrics.get("airUtilTx"), 2, "%"
|
||||
),
|
||||
}
|
||||
)
|
||||
raw_value = node.get(field)
|
||||
|
||||
row.update(
|
||||
{
|
||||
"SNR": formatFloat(node.get("snr"), 2, " dB"),
|
||||
"Hops Away": node.get("hopsAway", "0/unknown"),
|
||||
"Channel": node.get("channel", 0),
|
||||
"LastHeard": getLH(node.get("lastHeard")),
|
||||
"Since": getTimeAgo(node.get("lastHeard")),
|
||||
}
|
||||
)
|
||||
formatted_value: Optional[str] = ""
|
||||
|
||||
rows.append(row)
|
||||
# Some of these need special formatting or processing.
|
||||
if field == "channel":
|
||||
if raw_value is None:
|
||||
formatted_value = "0"
|
||||
elif field == "deviceMetrics.channelUtilization":
|
||||
formatted_value = formatFloat(raw_value, 2, "%")
|
||||
elif field == "deviceMetrics.airUtilTx":
|
||||
formatted_value = formatFloat(raw_value, 2, "%")
|
||||
elif field == "deviceMetrics.batteryLevel":
|
||||
if raw_value in (0, 101):
|
||||
formatted_value = "Powered"
|
||||
else:
|
||||
formatted_value = formatFloat(raw_value, 0, "%")
|
||||
elif field == "lastHeard":
|
||||
formatted_value = getLH(raw_value)
|
||||
elif field == "position.latitude":
|
||||
formatted_value = formatFloat(raw_value, 4, "°")
|
||||
elif field == "position.longitude":
|
||||
formatted_value = formatFloat(raw_value, 4, "°")
|
||||
elif field == "position.altitude":
|
||||
formatted_value = formatFloat(raw_value, 0, "m")
|
||||
elif field == "since":
|
||||
formatted_value = getTimeAgo(raw_value) or "N/A"
|
||||
elif field == "snr":
|
||||
formatted_value = formatFloat(raw_value, 0, " dB")
|
||||
elif field == "user.shortName":
|
||||
formatted_value = raw_value if raw_value is not None else f'Meshtastic {presumptive_id[-4:]}'
|
||||
elif field == "user.id":
|
||||
formatted_value = raw_value if raw_value is not None else presumptive_id
|
||||
else:
|
||||
formatted_value = raw_value # No special formatting
|
||||
|
||||
fields[field] = formatted_value
|
||||
|
||||
# Filter out any field in the data set that was not specified.
|
||||
filteredData = {get_human_readable(k): v for k, v in fields.items() if k in showFields}
|
||||
filteredData.update({get_human_readable(k): v for k, v in fields.items()})
|
||||
rows.append(filteredData)
|
||||
|
||||
rows.sort(key=lambda r: r.get("LastHeard") or "0000", reverse=True)
|
||||
for i, row in enumerate(rows):
|
||||
@@ -314,19 +374,33 @@ class MeshInterface: # pylint: disable=R0902
|
||||
return table
|
||||
|
||||
def getNode(
|
||||
self, nodeId: str, requestChannels: bool = True
|
||||
self, nodeId: str, requestChannels: bool = True, requestChannelAttempts: int = 3, timeout: int = 300
|
||||
) -> meshtastic.node.Node:
|
||||
"""Return a node object which contains device settings and channel info"""
|
||||
if nodeId in (LOCAL_ADDR, BROADCAST_ADDR):
|
||||
return self.localNode
|
||||
else:
|
||||
n = meshtastic.node.Node(self, nodeId)
|
||||
n = meshtastic.node.Node(self, nodeId, timeout=timeout)
|
||||
# Only request device settings and channel info when necessary
|
||||
if requestChannels:
|
||||
logging.debug("About to requestChannels")
|
||||
n.requestChannels()
|
||||
if not n.waitForConfig():
|
||||
our_exit("Error: Timed out waiting for channels")
|
||||
retries_left = requestChannelAttempts
|
||||
last_index: int = 0
|
||||
while retries_left > 0:
|
||||
retries_left -= 1
|
||||
if not n.waitForConfig():
|
||||
new_index: int = len(n.partialChannels) if n.partialChannels else 0
|
||||
# each time we get a new channel, reset the counter
|
||||
if new_index != last_index:
|
||||
retries_left = requestChannelAttempts - 1
|
||||
if retries_left <= 0:
|
||||
our_exit("Error: Timed out waiting for channels, giving up")
|
||||
print("Timed out trying to retrieve channel info, retrying")
|
||||
n.requestChannels(startingIndex=new_index)
|
||||
last_index = new_index
|
||||
else:
|
||||
break
|
||||
return n
|
||||
|
||||
def sendText(
|
||||
@@ -337,6 +411,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
wantResponse: bool = False,
|
||||
onResponse: Optional[Callable[[dict], Any]] = None,
|
||||
channelIndex: int = 0,
|
||||
portNum: portnums_pb2.PortNum.ValueType = portnums_pb2.PortNum.TEXT_MESSAGE_APP
|
||||
):
|
||||
"""Send a utf8 string to some other node, if the node has a display it
|
||||
will also be shown on the device.
|
||||
@@ -347,12 +422,12 @@ class MeshInterface: # pylint: disable=R0902
|
||||
Keyword Arguments:
|
||||
destinationId {nodeId or nodeNum} -- where to send this
|
||||
message (default: {BROADCAST_ADDR})
|
||||
portNum -- the application portnum (similar to IP port numbers)
|
||||
of the destination, see portnums.proto for a list
|
||||
wantAck -- True if you want the message sent in a reliable manner
|
||||
(with retries and ack/nak provided for delivery)
|
||||
wantResponse -- True if you want the service on the other side to
|
||||
send an application layer response
|
||||
portNum -- the application portnum (similar to IP port numbers)
|
||||
of the destination, see portnums.proto for a list
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
@@ -361,13 +436,47 @@ class MeshInterface: # pylint: disable=R0902
|
||||
return self.sendData(
|
||||
text.encode("utf-8"),
|
||||
destinationId,
|
||||
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
||||
portNum=portNum,
|
||||
wantAck=wantAck,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=channelIndex,
|
||||
)
|
||||
|
||||
|
||||
def sendAlert(
|
||||
self,
|
||||
text: str,
|
||||
destinationId: Union[int, str] = BROADCAST_ADDR,
|
||||
onResponse: Optional[Callable[[dict], Any]] = None,
|
||||
channelIndex: int = 0,
|
||||
):
|
||||
"""Send an alert text to some other node. This is similar to a text message,
|
||||
but carries a higher priority and is capable of generating special notifications
|
||||
on certain clients.
|
||||
|
||||
Arguments:
|
||||
text {string} -- The text of the alert to send
|
||||
|
||||
Keyword Arguments:
|
||||
destinationId {nodeId or nodeNum} -- where to send this
|
||||
message (default: {BROADCAST_ADDR})
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
|
||||
return self.sendData(
|
||||
text.encode("utf-8"),
|
||||
destinationId,
|
||||
portNum=portnums_pb2.PortNum.ALERT_APP,
|
||||
wantAck=False,
|
||||
wantResponse=False,
|
||||
onResponse=onResponse,
|
||||
channelIndex=channelIndex,
|
||||
priority=mesh_pb2.MeshPacket.Priority.ALERT
|
||||
)
|
||||
|
||||
def sendData(
|
||||
self,
|
||||
data,
|
||||
@@ -379,7 +488,10 @@ class MeshInterface: # pylint: disable=R0902
|
||||
onResponseAckPermitted: bool=False,
|
||||
channelIndex: int=0,
|
||||
hopLimit: Optional[int]=None,
|
||||
):
|
||||
pkiEncrypted: Optional[bool]=False,
|
||||
publicKey: Optional[bytes]=None,
|
||||
priority: mesh_pb2.MeshPacket.Priority.ValueType=mesh_pb2.MeshPacket.Priority.RELIABLE,
|
||||
): # pylint: disable=R0913
|
||||
"""Send a data packet to some other node
|
||||
|
||||
Keyword Arguments:
|
||||
@@ -430,11 +542,13 @@ class MeshInterface: # pylint: disable=R0902
|
||||
meshPacket.decoded.portnum = portNum
|
||||
meshPacket.decoded.want_response = wantResponse
|
||||
meshPacket.id = self._generatePacketId()
|
||||
if priority is not None:
|
||||
meshPacket.priority = priority
|
||||
|
||||
if onResponse is not None:
|
||||
logging.debug(f"Setting a response handler for requestId {meshPacket.id}")
|
||||
self._addResponseHandler(meshPacket.id, onResponse, ackPermitted=onResponseAckPermitted)
|
||||
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck, hopLimit=hopLimit)
|
||||
p = self._sendPacket(meshPacket, destinationId, wantAck=wantAck, hopLimit=hopLimit, pkiEncrypted=pkiEncrypted, publicKey=publicKey)
|
||||
return p
|
||||
|
||||
def sendPosition(
|
||||
@@ -539,17 +653,46 @@ class MeshInterface: # pylint: disable=R0902
|
||||
|
||||
def onResponseTraceRoute(self, p: dict):
|
||||
"""on response for trace route"""
|
||||
UNK_SNR = -128 # Value representing unknown SNR
|
||||
|
||||
routeDiscovery = mesh_pb2.RouteDiscovery()
|
||||
routeDiscovery.ParseFromString(p["decoded"]["payload"])
|
||||
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)
|
||||
|
||||
print("Route traced:")
|
||||
routeStr = self._nodeNumToId(p["to"]) or f"{p['to']:08x}"
|
||||
if "route" in asDict:
|
||||
for nodeNum in asDict["route"]:
|
||||
routeStr += " --> " + (self._nodeNumToId(nodeNum) or f"{nodeNum:08x}")
|
||||
routeStr += " --> " + (self._nodeNumToId(p["from"]) or f"{p['from']:08x}")
|
||||
print(routeStr)
|
||||
print("Route traced towards destination:")
|
||||
routeStr = self._nodeNumToId(p["to"], False) or f"{p['to']:08x}" # Start with destination of response
|
||||
|
||||
# SNR list should have one more entry than the route, as the final destination adds its SNR also
|
||||
lenTowards = 0 if "route" not in asDict else len(asDict["route"])
|
||||
snrTowardsValid = "snrTowards" in asDict and len(asDict["snrTowards"]) == lenTowards + 1
|
||||
if lenTowards > 0: # Loop through hops in route and add SNR if available
|
||||
for idx, nodeNum in enumerate(asDict["route"]):
|
||||
routeStr += " --> " + (self._nodeNumToId(nodeNum, False) or f"{nodeNum:08x}") \
|
||||
+ " (" + (str(asDict["snrTowards"][idx] / 4) if snrTowardsValid and asDict["snrTowards"][idx] != UNK_SNR else "?") + "dB)"
|
||||
|
||||
# End with origin of response
|
||||
routeStr += " --> " + (self._nodeNumToId(p["from"], False) or f"{p['from']:08x}") \
|
||||
+ " (" + (str(asDict["snrTowards"][-1] / 4) if snrTowardsValid and asDict["snrTowards"][-1] != UNK_SNR else "?") + "dB)"
|
||||
|
||||
print(routeStr) # Print the route towards destination
|
||||
|
||||
# Only if hopStart is set and there is an SNR entry (for the origin) it's valid, even though route might be empty (direct connection)
|
||||
lenBack = 0 if "routeBack" not in asDict else len(asDict["routeBack"])
|
||||
backValid = "hopStart" in p and "snrBack" in asDict and len(asDict["snrBack"]) == lenBack + 1
|
||||
if backValid:
|
||||
print("Route traced back to us:")
|
||||
routeStr = self._nodeNumToId(p["from"], False) or f"{p['from']:08x}" # Start with origin of response
|
||||
|
||||
if lenBack > 0: # Loop through hops in routeBack and add SNR if available
|
||||
for idx, nodeNum in enumerate(asDict["routeBack"]):
|
||||
routeStr += " --> " + (self._nodeNumToId(nodeNum, False) or f"{nodeNum:08x}") \
|
||||
+ " (" + (str(asDict["snrBack"][idx] / 4) if asDict["snrBack"][idx] != UNK_SNR else "?") + "dB)"
|
||||
|
||||
# End with destination of response (us)
|
||||
routeStr += " --> " + (self._nodeNumToId(p["to"], False) or f"{p['to']:08x}") \
|
||||
+ " (" + (str(asDict["snrBack"][-1] / 4) if asDict["snrBack"][-1] != UNK_SNR else "?") + "dB)"
|
||||
|
||||
print(routeStr) # Print the route back to us
|
||||
|
||||
self._acknowledgment.receivedTraceRoute = True
|
||||
|
||||
@@ -558,32 +701,40 @@ class MeshInterface: # pylint: disable=R0902
|
||||
destinationId: Union[int, str] = BROADCAST_ADDR,
|
||||
wantResponse: bool = False,
|
||||
channelIndex: int = 0,
|
||||
telemetryType: str = "device_metrics"
|
||||
):
|
||||
"""Send telemetry and optionally ask for a response"""
|
||||
r = telemetry_pb2.Telemetry()
|
||||
|
||||
if self.nodes is not None:
|
||||
node = next(
|
||||
n for n in self.nodes.values() if n["num"] == self.localNode.nodeNum
|
||||
)
|
||||
if node is not None:
|
||||
metrics = node.get("deviceMetrics")
|
||||
if metrics:
|
||||
batteryLevel = metrics.get("batteryLevel")
|
||||
if batteryLevel is not None:
|
||||
r.device_metrics.battery_level = batteryLevel
|
||||
voltage = metrics.get("voltage")
|
||||
if voltage is not None:
|
||||
r.device_metrics.voltage = voltage
|
||||
channel_utilization = metrics.get("channelUtilization")
|
||||
if channel_utilization is not None:
|
||||
r.device_metrics.channel_utilization = channel_utilization
|
||||
air_util_tx = metrics.get("airUtilTx")
|
||||
if air_util_tx is not None:
|
||||
r.device_metrics.air_util_tx = air_util_tx
|
||||
uptime_seconds = metrics.get("uptimeSeconds")
|
||||
if uptime_seconds is not None:
|
||||
r.device_metrics.uptime_seconds = uptime_seconds
|
||||
if telemetryType == "environment_metrics":
|
||||
r.environment_metrics.CopyFrom(telemetry_pb2.EnvironmentMetrics())
|
||||
elif telemetryType == "air_quality_metrics":
|
||||
r.air_quality_metrics.CopyFrom(telemetry_pb2.AirQualityMetrics())
|
||||
elif telemetryType == "power_metrics":
|
||||
r.power_metrics.CopyFrom(telemetry_pb2.PowerMetrics())
|
||||
elif telemetryType == "local_stats":
|
||||
r.local_stats.CopyFrom(telemetry_pb2.LocalStats())
|
||||
else: # fall through to device metrics
|
||||
if self.nodesByNum is not None:
|
||||
node = self.nodesByNum.get(self.localNode.nodeNum)
|
||||
if node is not None:
|
||||
metrics = node.get("deviceMetrics")
|
||||
if metrics:
|
||||
batteryLevel = metrics.get("batteryLevel")
|
||||
if batteryLevel is not None:
|
||||
r.device_metrics.battery_level = batteryLevel
|
||||
voltage = metrics.get("voltage")
|
||||
if voltage is not None:
|
||||
r.device_metrics.voltage = voltage
|
||||
channel_utilization = metrics.get("channelUtilization")
|
||||
if channel_utilization is not None:
|
||||
r.device_metrics.channel_utilization = channel_utilization
|
||||
air_util_tx = metrics.get("airUtilTx")
|
||||
if air_util_tx is not None:
|
||||
r.device_metrics.air_util_tx = air_util_tx
|
||||
uptime_seconds = metrics.get("uptimeSeconds")
|
||||
if uptime_seconds is not None:
|
||||
r.device_metrics.uptime_seconds = uptime_seconds
|
||||
|
||||
if wantResponse:
|
||||
onResponse = self.onResponseTelemetry
|
||||
@@ -607,22 +758,32 @@ class MeshInterface: # pylint: disable=R0902
|
||||
self._acknowledgment.receivedTelemetry = True
|
||||
telemetry = telemetry_pb2.Telemetry()
|
||||
telemetry.ParseFromString(p["decoded"]["payload"])
|
||||
|
||||
print("Telemetry received:")
|
||||
if telemetry.device_metrics.battery_level is not None:
|
||||
print(f"Battery level: {telemetry.device_metrics.battery_level:.2f}%")
|
||||
if telemetry.device_metrics.voltage is not None:
|
||||
print(f"Voltage: {telemetry.device_metrics.voltage:.2f} V")
|
||||
if telemetry.device_metrics.channel_utilization is not None:
|
||||
print(
|
||||
f"Total channel utilization: {telemetry.device_metrics.channel_utilization:.2f}%"
|
||||
)
|
||||
if telemetry.device_metrics.air_util_tx is not None:
|
||||
print(
|
||||
f"Transmit air utilization: {telemetry.device_metrics.air_util_tx:.2f}%"
|
||||
)
|
||||
if telemetry.device_metrics.uptime_seconds is not None:
|
||||
print(f"Uptime: {telemetry.device_metrics.uptime_seconds} s")
|
||||
# Check if the telemetry message has the device_metrics field
|
||||
# This is the original code that was the default for --request-telemetry and is kept for compatibility
|
||||
if telemetry.HasField("device_metrics"):
|
||||
if telemetry.device_metrics.battery_level is not None:
|
||||
print(f"Battery level: {telemetry.device_metrics.battery_level:.2f}%")
|
||||
if telemetry.device_metrics.voltage is not None:
|
||||
print(f"Voltage: {telemetry.device_metrics.voltage:.2f} V")
|
||||
if telemetry.device_metrics.channel_utilization is not None:
|
||||
print(
|
||||
f"Total channel utilization: {telemetry.device_metrics.channel_utilization:.2f}%"
|
||||
)
|
||||
if telemetry.device_metrics.air_util_tx is not None:
|
||||
print(
|
||||
f"Transmit air utilization: {telemetry.device_metrics.air_util_tx:.2f}%"
|
||||
)
|
||||
if telemetry.device_metrics.uptime_seconds is not None:
|
||||
print(f"Uptime: {telemetry.device_metrics.uptime_seconds} s")
|
||||
else:
|
||||
# this is the new code if --request-telemetry <type> is used.
|
||||
telemetry_dict = google.protobuf.json_format.MessageToDict(telemetry)
|
||||
for key, value in telemetry_dict.items():
|
||||
if key != "time": # protobuf includes a time field that we don't print for device_metrics.
|
||||
print(f"{key}:")
|
||||
for sub_key, sub_value in value.items():
|
||||
print(f" {sub_key}: {sub_value}")
|
||||
|
||||
elif p["decoded"]["portnum"] == "ROUTING_APP":
|
||||
if p["decoded"]["routing"]["errorReason"] == "NO_RESPONSE":
|
||||
@@ -630,6 +791,113 @@ class MeshInterface: # pylint: disable=R0902
|
||||
"No response from node. At least firmware 2.1.22 is required on the destination node."
|
||||
)
|
||||
|
||||
def onResponseWaypoint(self, p: dict):
|
||||
"""on response for waypoint"""
|
||||
if p["decoded"]["portnum"] == "WAYPOINT_APP":
|
||||
self._acknowledgment.receivedWaypoint = True
|
||||
w = mesh_pb2.Waypoint()
|
||||
w.ParseFromString(p["decoded"]["payload"])
|
||||
print(f"Waypoint received: {w}")
|
||||
elif p["decoded"]["portnum"] == "ROUTING_APP":
|
||||
if p["decoded"]["routing"]["errorReason"] == "NO_RESPONSE":
|
||||
our_exit(
|
||||
"No response from node. At least firmware 2.1.22 is required on the destination node."
|
||||
)
|
||||
|
||||
def sendWaypoint(
|
||||
self,
|
||||
name,
|
||||
description,
|
||||
expire: int,
|
||||
waypoint_id: Optional[int] = None,
|
||||
latitude: float = 0.0,
|
||||
longitude: float = 0.0,
|
||||
destinationId: Union[int, str] = BROADCAST_ADDR,
|
||||
wantAck: bool = True,
|
||||
wantResponse: bool = False,
|
||||
channelIndex: int = 0,
|
||||
): # pylint: disable=R0913
|
||||
"""
|
||||
Send a waypoint packet to some other node (normally a broadcast)
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet and
|
||||
can be used to track future message acks/naks.
|
||||
"""
|
||||
w = mesh_pb2.Waypoint()
|
||||
w.name = name
|
||||
w.description = description
|
||||
w.expire = expire
|
||||
if waypoint_id is None:
|
||||
# Generate a waypoint's id, NOT a packet ID.
|
||||
# same algorithm as https://github.com/meshtastic/js/blob/715e35d2374276a43ffa93c628e3710875d43907/src/meshDevice.ts#L791
|
||||
seed = secrets.randbits(32)
|
||||
w.id = math.floor(seed * math.pow(2, -32) * 1e9)
|
||||
logging.debug(f"w.id:{w.id}")
|
||||
else:
|
||||
w.id = waypoint_id
|
||||
if latitude != 0.0:
|
||||
w.latitude_i = int(latitude * 1e7)
|
||||
logging.debug(f"w.latitude_i:{w.latitude_i}")
|
||||
if longitude != 0.0:
|
||||
w.longitude_i = int(longitude * 1e7)
|
||||
logging.debug(f"w.longitude_i:{w.longitude_i}")
|
||||
|
||||
if wantResponse:
|
||||
onResponse = self.onResponseWaypoint
|
||||
else:
|
||||
onResponse = None
|
||||
|
||||
d = self.sendData(
|
||||
w,
|
||||
destinationId,
|
||||
portNum=portnums_pb2.PortNum.WAYPOINT_APP,
|
||||
wantAck=wantAck,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=channelIndex,
|
||||
)
|
||||
if wantResponse:
|
||||
self.waitForWaypoint()
|
||||
return d
|
||||
|
||||
def deleteWaypoint(
|
||||
self,
|
||||
waypoint_id: int,
|
||||
destinationId: Union[int, str] = BROADCAST_ADDR,
|
||||
wantAck: bool = True,
|
||||
wantResponse: bool = False,
|
||||
channelIndex: int = 0,
|
||||
):
|
||||
"""
|
||||
Send a waypoint deletion packet to some other node (normally a broadcast)
|
||||
|
||||
NB: The id must be the waypoint's id and not the id of the packet creation.
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet and
|
||||
can be used to track future message acks/naks.
|
||||
"""
|
||||
p = mesh_pb2.Waypoint()
|
||||
p.id = waypoint_id
|
||||
p.expire = 0
|
||||
|
||||
if wantResponse:
|
||||
onResponse = self.onResponseWaypoint
|
||||
else:
|
||||
onResponse = None
|
||||
|
||||
d = self.sendData(
|
||||
p,
|
||||
destinationId,
|
||||
portNum=portnums_pb2.PortNum.WAYPOINT_APP,
|
||||
wantAck=wantAck,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=channelIndex,
|
||||
)
|
||||
if wantResponse:
|
||||
self.waitForWaypoint()
|
||||
return d
|
||||
|
||||
def _addResponseHandler(
|
||||
self,
|
||||
requestId: int,
|
||||
@@ -645,7 +913,9 @@ class MeshInterface: # pylint: disable=R0902
|
||||
meshPacket: mesh_pb2.MeshPacket,
|
||||
destinationId: Union[int,str]=BROADCAST_ADDR,
|
||||
wantAck: bool=False,
|
||||
hopLimit: Optional[int]=None
|
||||
hopLimit: Optional[int]=None,
|
||||
pkiEncrypted: Optional[bool]=False,
|
||||
publicKey: Optional[bytes]=None,
|
||||
):
|
||||
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
||||
You probably don't want this - use sendData instead.
|
||||
@@ -673,8 +943,10 @@ class MeshInterface: # pylint: disable=R0902
|
||||
else:
|
||||
our_exit("Warning: No myInfo found.")
|
||||
# A simple hex style nodeid - we can parse this without needing the DB
|
||||
elif destinationId.startswith("!"):
|
||||
nodeNum = int(destinationId[1:], 16)
|
||||
elif isinstance(destinationId, str) and len(destinationId) >= 8:
|
||||
# assuming some form of node id string such as !1234578 or 0x12345678
|
||||
# always grab the last 8 items of the hexadecimal id str and parse to integer
|
||||
nodeNum = int(destinationId[-8:], 16)
|
||||
else:
|
||||
if self.nodes:
|
||||
node = self.nodes.get(destinationId)
|
||||
@@ -694,6 +966,12 @@ class MeshInterface: # pylint: disable=R0902
|
||||
loraConfig = getattr(self.localNode.localConfig, "lora")
|
||||
meshPacket.hop_limit = getattr(loraConfig, "hop_limit")
|
||||
|
||||
if pkiEncrypted:
|
||||
meshPacket.pki_encrypted = True
|
||||
|
||||
if publicKey is not None:
|
||||
meshPacket.public_key = publicKey
|
||||
|
||||
# if the user hasn't set an ID for this packet (likely and recommended),
|
||||
# we should pick a new unique ID so the message can be tracked.
|
||||
if meshPacket.id == 0:
|
||||
@@ -702,7 +980,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
toRadio.packet.CopyFrom(meshPacket)
|
||||
if self.noProto:
|
||||
logging.warning(
|
||||
f"Not sending packet because protocol use is disabled by noProto"
|
||||
"Not sending packet because protocol use is disabled by noProto"
|
||||
)
|
||||
else:
|
||||
logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
@@ -746,6 +1024,12 @@ class MeshInterface: # pylint: disable=R0902
|
||||
if not success:
|
||||
raise MeshInterface.MeshInterfaceError("Timed out waiting for position")
|
||||
|
||||
def waitForWaypoint(self):
|
||||
"""Wait for waypoint"""
|
||||
success = self._timeout.waitForWaypoint(self._acknowledgment)
|
||||
if not success:
|
||||
raise MeshInterface.MeshInterfaceError("Timed out waiting for waypoint")
|
||||
|
||||
def getMyNodeInfo(self) -> Optional[Dict]:
|
||||
"""Get info about my node."""
|
||||
if self.myInfo is None or self.nodesByNum is None:
|
||||
@@ -774,6 +1058,13 @@ class MeshInterface: # pylint: disable=R0902
|
||||
return user.get("shortName", None)
|
||||
return None
|
||||
|
||||
def getPublicKey(self):
|
||||
"""Get Public Key"""
|
||||
user = self.getMyUser()
|
||||
if user is not None:
|
||||
return user.get("publicKey", None)
|
||||
return None
|
||||
|
||||
def _waitConnected(self, timeout=30.0):
|
||||
"""Block until the initial node db download is complete, or timeout
|
||||
and raise an exception"""
|
||||
@@ -794,7 +1085,10 @@ class MeshInterface: # pylint: disable=R0902
|
||||
"Not connected yet, can not generate packet"
|
||||
)
|
||||
else:
|
||||
self.currentPacketId = (self.currentPacketId + 1) & 0xFFFFFFFF
|
||||
nextPacketId = (self.currentPacketId + 1) & 0xFFFFFFFF
|
||||
nextPacketId = nextPacketId & 0x3FF # == (0xFFFFFFFF >> 22), masks upper 22 bits
|
||||
randomPart = (random.randint(0, 0x3FFFFF) << 10) & 0xFFFFFFFF # generate number with 10 zeros at end
|
||||
self.currentPacketId = nextPacketId | randomPart # combine
|
||||
return self.currentPacketId
|
||||
|
||||
def _disconnected(self):
|
||||
@@ -849,6 +1143,8 @@ class MeshInterface: # pylint: disable=R0902
|
||||
startConfig = mesh_pb2.ToRadio()
|
||||
if self.configId is None or not self.noNodes:
|
||||
self.configId = random.randint(0, 0xFFFFFFFF)
|
||||
if self.configId == NODELESS_WANT_CONFIG_ID:
|
||||
self.configId = self.configId + 1
|
||||
startConfig.want_config_id = self.configId
|
||||
self._sendToRadio(startConfig)
|
||||
|
||||
@@ -873,7 +1169,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
if self.noProto:
|
||||
logging.warning(
|
||||
f"Not sending packet because protocol use is disabled by noProto"
|
||||
"Not sending packet because protocol use is disabled by noProto"
|
||||
)
|
||||
else:
|
||||
# logging.debug(f"Sending toRadio: {stripnl(toRadio)}")
|
||||
@@ -959,10 +1255,17 @@ class MeshInterface: # pylint: disable=R0902
|
||||
|
||||
Called by subclasses."""
|
||||
fromRadio = mesh_pb2.FromRadio()
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
logging.debug(
|
||||
f"in mesh_interface.py _handleFromRadio() fromRadioBytes: {fromRadioBytes}"
|
||||
)
|
||||
try:
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
except Exception as ex:
|
||||
logging.error(
|
||||
f"Error while parsing FromRadio bytes:{fromRadioBytes} {ex}"
|
||||
)
|
||||
traceback.print_exc()
|
||||
raise ex
|
||||
asDict = google.protobuf.json_format.MessageToDict(fromRadio)
|
||||
logging.debug(f"Received from radio: {fromRadio}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
@@ -1051,7 +1354,10 @@ class MeshInterface: # pylint: disable=R0902
|
||||
self.localNode.localConfig.bluetooth.CopyFrom(
|
||||
fromRadio.config.bluetooth
|
||||
)
|
||||
|
||||
elif fromRadio.config.HasField("security"):
|
||||
self.localNode.localConfig.security.CopyFrom(
|
||||
fromRadio.config.security
|
||||
)
|
||||
elif fromRadio.moduleConfig.HasField("mqtt"):
|
||||
self.localNode.moduleConfig.mqtt.CopyFrom(fromRadio.moduleConfig.mqtt)
|
||||
elif fromRadio.moduleConfig.HasField("serial"):
|
||||
@@ -1117,17 +1423,21 @@ class MeshInterface: # pylint: disable=R0902
|
||||
position["longitude"] = float(position["longitudeI"] * Decimal("1e-7"))
|
||||
return position
|
||||
|
||||
def _nodeNumToId(self, num: int) -> Optional[str]:
|
||||
def _nodeNumToId(self, num: int, isDest = True) -> Optional[str]:
|
||||
"""Map a node node number to a node ID
|
||||
|
||||
Arguments:
|
||||
num {int} -- Node number
|
||||
isDest {bool} -- True if the node number is a destination (to show broadcast address or unknown node)
|
||||
|
||||
Returns:
|
||||
string -- Node ID
|
||||
"""
|
||||
if num == BROADCAST_NUM:
|
||||
return BROADCAST_ADDR
|
||||
if isDest:
|
||||
return BROADCAST_ADDR
|
||||
else:
|
||||
return "Unknown"
|
||||
|
||||
try:
|
||||
return self.nodesByNum[num]["user"]["id"] # type: ignore[index]
|
||||
@@ -1200,7 +1510,7 @@ class MeshInterface: # pylint: disable=R0902
|
||||
|
||||
# /add fromId and toId fields based on the node ID
|
||||
try:
|
||||
asDict["fromId"] = self._nodeNumToId(asDict["from"])
|
||||
asDict["fromId"] = self._nodeNumToId(asDict["from"], False)
|
||||
except Exception as ex:
|
||||
logging.warning(f"Not populating fromId {ex}")
|
||||
try:
|
||||
|
||||
@@ -13,6 +13,8 @@ with rather more easily once the code is simplified by this change.
|
||||
|
||||
"""
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
def reset():
|
||||
"""
|
||||
Restore the namespace to pristine condition.
|
||||
@@ -33,5 +35,5 @@ args = None
|
||||
parser = None
|
||||
channel_index = None
|
||||
logfile = None
|
||||
tunnelInstance = None
|
||||
tunnelInstance: Optional[Any] = None
|
||||
camel_case = False
|
||||
|
||||
@@ -5,7 +5,7 @@ import base64
|
||||
import logging
|
||||
import time
|
||||
|
||||
from typing import Optional, Union
|
||||
from typing import Optional, Union, List
|
||||
|
||||
from meshtastic.protobuf import admin_pb2, apponly_pb2, channel_pb2, localonly_pb2, mesh_pb2, portnums_pb2
|
||||
from meshtastic.util import (
|
||||
@@ -25,15 +25,15 @@ class Node:
|
||||
Includes methods for localConfig, moduleConfig and channels
|
||||
"""
|
||||
|
||||
def __init__(self, iface, nodeNum, noProto=False):
|
||||
def __init__(self, iface, nodeNum, noProto=False, timeout: int = 300):
|
||||
"""Constructor"""
|
||||
self.iface = iface
|
||||
self.nodeNum = nodeNum
|
||||
self.localConfig = localonly_pb2.LocalConfig()
|
||||
self.moduleConfig = localonly_pb2.LocalModuleConfig()
|
||||
self.channels = None
|
||||
self._timeout = Timeout(maxSecs=300)
|
||||
self.partialChannels = None
|
||||
self._timeout = Timeout(maxSecs=timeout)
|
||||
self.partialChannels: Optional[List] = None
|
||||
self.noProto = noProto
|
||||
self.cannedPluginMessage = None
|
||||
self.cannedPluginMessageMessages = None
|
||||
@@ -77,17 +77,19 @@ class Node:
|
||||
self.channels = channels
|
||||
self._fixupChannels()
|
||||
|
||||
def requestChannels(self):
|
||||
def requestChannels(self, startingIndex: int = 0):
|
||||
"""Send regular MeshPackets to ask channels."""
|
||||
logging.debug(f"requestChannels for nodeNum:{self.nodeNum}")
|
||||
self.channels = None
|
||||
self.partialChannels = [] # We keep our channels in a temp array until finished
|
||||
|
||||
self._requestChannel(0)
|
||||
# only initialize if we're starting out fresh
|
||||
if startingIndex == 0:
|
||||
self.channels = None
|
||||
self.partialChannels = [] # We keep our channels in a temp array until finished
|
||||
self._requestChannel(startingIndex)
|
||||
|
||||
def onResponseRequestSettings(self, p):
|
||||
"""Handle the response packets for requesting settings _requestSettings()"""
|
||||
logging.debug(f"onResponseRequestSetting() p:{p}")
|
||||
config_values = None
|
||||
if "routing" in p["decoded"]:
|
||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
|
||||
@@ -97,13 +99,16 @@ class Node:
|
||||
print("")
|
||||
adminMessage = p["decoded"]["admin"]
|
||||
if "getConfigResponse" in adminMessage:
|
||||
oneof = "get_config_response"
|
||||
resp = adminMessage["getConfigResponse"]
|
||||
field = list(resp.keys())[0]
|
||||
config_type = self.localConfig.DESCRIPTOR.fields_by_name.get(
|
||||
camel_to_snake(field)
|
||||
)
|
||||
config_values = getattr(self.localConfig, config_type.name)
|
||||
if config_type is not None:
|
||||
config_values = getattr(self.localConfig, config_type.name)
|
||||
elif "getModuleConfigResponse" in adminMessage:
|
||||
oneof = "get_module_config_response"
|
||||
resp = adminMessage["getModuleConfigResponse"]
|
||||
field = list(resp.keys())[0]
|
||||
config_type = self.moduleConfig.DESCRIPTOR.fields_by_name.get(
|
||||
@@ -115,9 +120,10 @@ class Node:
|
||||
"Did not receive a valid response. Make sure to have a shared channel named 'admin'."
|
||||
)
|
||||
return
|
||||
for key, value in resp[field].items():
|
||||
setattr(config_values, camel_to_snake(key), value)
|
||||
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}")
|
||||
if config_values is not None:
|
||||
raw_config = getattr(getattr(adminMessage['raw'], oneof), camel_to_snake(field))
|
||||
config_values.CopyFrom(raw_config)
|
||||
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}")
|
||||
|
||||
def requestConfig(self, configType):
|
||||
"""Request the config from the node via admin message"""
|
||||
@@ -126,16 +132,18 @@ class Node:
|
||||
else:
|
||||
onResponse = self.onResponseRequestSettings
|
||||
print("Requesting current config from remote node (this can take a while).")
|
||||
p = admin_pb2.AdminMessage()
|
||||
if isinstance(configType, int):
|
||||
p.get_config_request = configType
|
||||
|
||||
msgIndex = configType.index
|
||||
if configType.containing_type.name == "LocalConfig":
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.get_config_request = msgIndex
|
||||
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
else:
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.get_module_config_request = msgIndex
|
||||
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
msgIndex = configType.index
|
||||
if configType.containing_type.name == "LocalConfig":
|
||||
p.get_config_request = msgIndex
|
||||
else:
|
||||
p.get_module_config_request = msgIndex
|
||||
|
||||
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
if onResponse:
|
||||
self.iface.waitForAckNak()
|
||||
|
||||
@@ -170,6 +178,8 @@ class Node:
|
||||
p.set_config.lora.CopyFrom(self.localConfig.lora)
|
||||
elif config_name == "bluetooth":
|
||||
p.set_config.bluetooth.CopyFrom(self.localConfig.bluetooth)
|
||||
elif config_name == "security":
|
||||
p.set_config.security.CopyFrom(self.localConfig.security)
|
||||
elif config_name == "mqtt":
|
||||
p.set_module_config.mqtt.CopyFrom(self.moduleConfig.mqtt)
|
||||
elif config_name == "serial":
|
||||
@@ -214,7 +224,7 @@ class Node:
|
||||
|
||||
def writeChannel(self, channelIndex, adminIndex=0):
|
||||
"""Write the current (edited) channel to the device"""
|
||||
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.set_channel.CopyFrom(self.channels[channelIndex])
|
||||
self._sendAdmin(p, adminIndex=adminIndex)
|
||||
@@ -282,6 +292,7 @@ class Node:
|
||||
def setOwner(self, long_name: Optional[str]=None, short_name: Optional[str]=None, is_licensed: bool=False):
|
||||
"""Set device owner name"""
|
||||
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
|
||||
nChars = 4
|
||||
@@ -326,14 +337,19 @@ class Node:
|
||||
s = s.replace("=", "").replace("+", "-").replace("/", "_")
|
||||
return f"https://meshtastic.org/e/#{s}"
|
||||
|
||||
def setURL(self, url):
|
||||
def setURL(self, url: str, addOnly: bool = False):
|
||||
"""Set mesh network URL"""
|
||||
if self.localConfig is None:
|
||||
our_exit("Warning: No Config has been read")
|
||||
if self.localConfig is None or self.channels is None:
|
||||
our_exit("Warning: config or channels not loaded")
|
||||
|
||||
# URLs are of the form https://meshtastic.org/d/#{base64_channel_set}
|
||||
# Split on '/#' to find the base64 encoded channel settings
|
||||
splitURL = url.split("/#")
|
||||
if addOnly:
|
||||
splitURL = url.split("/?add=true#")
|
||||
else:
|
||||
splitURL = url.split("/#")
|
||||
if len(splitURL) == 1:
|
||||
our_exit(f"Warning: Invalid URL '{url}'")
|
||||
b64 = splitURL[-1]
|
||||
|
||||
# We normally strip padding to make for a shorter URL, but the python parser doesn't like
|
||||
@@ -350,23 +366,40 @@ class Node:
|
||||
if len(channelSet.settings) == 0:
|
||||
our_exit("Warning: There were no settings.")
|
||||
|
||||
i = 0
|
||||
for chs in channelSet.settings:
|
||||
ch = channel_pb2.Channel()
|
||||
ch.role = (
|
||||
channel_pb2.Channel.Role.PRIMARY
|
||||
if i == 0
|
||||
else channel_pb2.Channel.Role.SECONDARY
|
||||
)
|
||||
ch.index = i
|
||||
ch.settings.CopyFrom(chs)
|
||||
self.channels[ch.index] = ch
|
||||
logging.debug(f"Channel i:{i} ch:{ch}")
|
||||
self.writeChannel(ch.index)
|
||||
i = i + 1
|
||||
if addOnly:
|
||||
# Add new channels with names not already present
|
||||
# Don't change existing channels
|
||||
for chs in channelSet.settings:
|
||||
channelExists = self.getChannelByName(chs.name)
|
||||
if channelExists or chs.name == "":
|
||||
print(f"Ignoring existing or empty channel \"{chs.name}\" from add URL")
|
||||
continue
|
||||
ch = self.getDisabledChannel()
|
||||
if not ch:
|
||||
our_exit("Warning: No free channels were found")
|
||||
ch.settings.CopyFrom(chs)
|
||||
ch.role = channel_pb2.Channel.Role.SECONDARY
|
||||
print(f"Adding new channel '{chs.name}' to device")
|
||||
self.writeChannel(ch.index)
|
||||
else:
|
||||
i = 0
|
||||
for chs in channelSet.settings:
|
||||
ch = channel_pb2.Channel()
|
||||
ch.role = (
|
||||
channel_pb2.Channel.Role.PRIMARY
|
||||
if i == 0
|
||||
else channel_pb2.Channel.Role.SECONDARY
|
||||
)
|
||||
ch.index = i
|
||||
ch.settings.CopyFrom(chs)
|
||||
self.channels[ch.index] = ch
|
||||
logging.debug(f"Channel i:{i} ch:{ch}")
|
||||
self.writeChannel(ch.index)
|
||||
i = i + 1
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.set_config.lora.CopyFrom(channelSet.lora_config)
|
||||
self.ensureSessionKey()
|
||||
self._sendAdmin(p)
|
||||
|
||||
def onResponseRequestRingtone(self, p):
|
||||
@@ -415,7 +448,7 @@ class Node:
|
||||
|
||||
if len(ringtone) > 230:
|
||||
our_exit("Warning: The ringtone must be less than 230 characters.")
|
||||
|
||||
self.ensureSessionKey()
|
||||
# split into chunks
|
||||
chunks = []
|
||||
chunks_size = 230
|
||||
@@ -491,7 +524,7 @@ class Node:
|
||||
|
||||
if len(message) > 200:
|
||||
our_exit("Warning: The canned message must be less than 200 characters.")
|
||||
|
||||
self.ensureSessionKey()
|
||||
# split into chunks
|
||||
chunks = []
|
||||
chunks_size = 200
|
||||
@@ -518,6 +551,7 @@ class Node:
|
||||
def exitSimulator(self):
|
||||
"""Tell a simulator node to exit (this message
|
||||
is ignored for other nodes)"""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.exit_simulator = True
|
||||
logging.debug("in exitSimulator()")
|
||||
@@ -526,6 +560,7 @@ class Node:
|
||||
|
||||
def reboot(self, secs: int = 10):
|
||||
"""Tell the node to reboot."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.reboot_seconds = secs
|
||||
logging.info(f"Telling node to reboot in {secs} seconds")
|
||||
@@ -539,6 +574,7 @@ class Node:
|
||||
|
||||
def beginSettingsTransaction(self):
|
||||
"""Tell the node to open a transaction to edit settings."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.begin_edit_settings = True
|
||||
logging.info(f"Telling open a transaction to edit settings")
|
||||
@@ -552,6 +588,7 @@ class Node:
|
||||
|
||||
def commitSettingsTransaction(self):
|
||||
"""Tell the node to commit the open transaction for editing settings."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.commit_edit_settings = True
|
||||
logging.info(f"Telling node to commit open transaction for editing settings")
|
||||
@@ -565,6 +602,7 @@ class Node:
|
||||
|
||||
def rebootOTA(self, secs: int = 10):
|
||||
"""Tell the node to reboot into factory firmware."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.reboot_ota_seconds = secs
|
||||
logging.info(f"Telling node to reboot to OTA in {secs} seconds")
|
||||
@@ -578,6 +616,7 @@ class Node:
|
||||
|
||||
def enterDFUMode(self):
|
||||
"""Tell the node to enter DFU mode (NRF52)."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.enter_dfu_mode_request = True
|
||||
logging.info(f"Telling node to enable DFU mode")
|
||||
@@ -591,6 +630,7 @@ class Node:
|
||||
|
||||
def shutdown(self, secs: int = 10):
|
||||
"""Tell the node to shutdown."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.shutdown_seconds = secs
|
||||
logging.info(f"Telling node to shutdown in {secs} seconds")
|
||||
@@ -613,11 +653,16 @@ class Node:
|
||||
)
|
||||
self.iface.waitForAckNak()
|
||||
|
||||
def factoryReset(self):
|
||||
def factoryReset(self, full: bool = False):
|
||||
"""Tell the node to factory reset."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.factory_reset = True
|
||||
logging.info(f"Telling node to factory reset")
|
||||
if full:
|
||||
p.factory_reset_device = True
|
||||
logging.info(f"Telling node to factory reset (full device reset)")
|
||||
else:
|
||||
p.factory_reset_config = True
|
||||
logging.info(f"Telling node to factory reset (config reset)")
|
||||
|
||||
# If sending to a remote node, wait for ACK/NAK
|
||||
if self == self.iface.localNode:
|
||||
@@ -628,6 +673,7 @@ class Node:
|
||||
|
||||
def removeNode(self, nodeId: Union[int, str]):
|
||||
"""Tell the node to remove a specific node by ID"""
|
||||
self.ensureSessionKey()
|
||||
if isinstance(nodeId, str):
|
||||
if nodeId.startswith("!"):
|
||||
nodeId = int(nodeId[1:], 16)
|
||||
@@ -643,8 +689,120 @@ class Node:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def setFavorite(self, nodeId: Union[int, str]):
|
||||
"""Tell the node to set the specified node ID to be favorited on the NodeDB on the device"""
|
||||
self.ensureSessionKey()
|
||||
if isinstance(nodeId, str):
|
||||
if nodeId.startswith("!"):
|
||||
nodeId = int(nodeId[1:], 16)
|
||||
else:
|
||||
nodeId = int(nodeId)
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.set_favorite_node = nodeId
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def backupPreferences(self, location: Optional[admin_pb2.AdminMessage.BackupLocation.ValueType] = 0):
|
||||
"""Tell the node to backup preferences to flash."""
|
||||
self.ensureSessionKey()
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.backup_preferences = location
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def restorePreferences(self, location: Optional[admin_pb2.AdminMessage.BackupLocation.ValueType] = 0):
|
||||
"""Tell the node to restore preferences from backup."""
|
||||
self.ensureSessionKey()
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.restore_preferences = location
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def removePreferencesBackups(self, location: Optional[admin_pb2.AdminMessage.BackupLocation.ValueType] = 0):
|
||||
"""Tell the node to remove backup preferences from the filesystem."""
|
||||
self.ensureSessionKey()
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.remove_backup_preferences = location
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def removeFavorite(self, nodeId: Union[int, str]):
|
||||
"""Tell the node to set the specified node ID to be un-favorited on the NodeDB on the device."""
|
||||
self.ensureSessionKey()
|
||||
if isinstance(nodeId, str):
|
||||
if nodeId.startswith("!"):
|
||||
nodeId = int(nodeId[1:], 16)
|
||||
else:
|
||||
nodeId = int(nodeId)
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.remove_favorite_node = nodeId
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def setIgnored(self, nodeId: Union[int, str]):
|
||||
"""Tell the node to set the specified node ID to be ignored on the NodeDB on the device"""
|
||||
self.ensureSessionKey()
|
||||
if isinstance(nodeId, str):
|
||||
if nodeId.startswith("!"):
|
||||
nodeId = int(nodeId[1:], 16)
|
||||
else:
|
||||
nodeId = int(nodeId)
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.set_ignored_node = nodeId
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def removeIgnored(self, nodeId: Union[int, str]):
|
||||
"""Tell the node to set the specified node ID to be un-ignored on the NodeDB on the device"""
|
||||
self.ensureSessionKey()
|
||||
if isinstance(nodeId, str):
|
||||
if nodeId.startswith("!"):
|
||||
nodeId = int(nodeId[1:], 16)
|
||||
else:
|
||||
nodeId = int(nodeId)
|
||||
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.remove_ignored_node = nodeId
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def resetNodeDb(self):
|
||||
"""Tell the node to reset its list of nodes."""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.nodedb_reset = True
|
||||
logging.info(f"Telling node to reset the NodeDB")
|
||||
@@ -658,9 +816,7 @@ class Node:
|
||||
|
||||
def setFixedPosition(self, lat: Union[int, float], lon: Union[int, float], alt: int):
|
||||
"""Tell the node to set fixed position to the provided value and enable the fixed position setting"""
|
||||
if self != self.iface.localNode:
|
||||
logging.error("Setting position of remote nodes is not supported.")
|
||||
return None
|
||||
self.ensureSessionKey()
|
||||
|
||||
p = mesh_pb2.Position()
|
||||
if isinstance(lat, float) and lat != 0.0:
|
||||
@@ -678,15 +834,40 @@ class Node:
|
||||
|
||||
a = admin_pb2.AdminMessage()
|
||||
a.set_fixed_position.CopyFrom(p)
|
||||
return self._sendAdmin(a)
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(a, onResponse=onResponse)
|
||||
|
||||
def removeFixedPosition(self):
|
||||
"""Tell the node to remove the fixed position and set the fixed position setting to false"""
|
||||
self.ensureSessionKey()
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.remove_fixed_position = True
|
||||
logging.info(f"Telling node to remove fixed position")
|
||||
|
||||
return self._sendAdmin(p)
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def setTime(self, timeSec: int = 0):
|
||||
"""Tell the node to set its time to the provided timestamp, or the system's current time if not provided or 0."""
|
||||
self.ensureSessionKey()
|
||||
if timeSec == 0:
|
||||
timeSec = int(time.time())
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.set_time_only = timeSec
|
||||
logging.info(f"Setting node time to {timeSec}")
|
||||
|
||||
if self == self.iface.localNode:
|
||||
onResponse = None
|
||||
else:
|
||||
onResponse = self.onAckNak
|
||||
return self._sendAdmin(p, onResponse=onResponse)
|
||||
|
||||
def _fixupChannels(self):
|
||||
"""Fixup indexes and add disabled channels as needed"""
|
||||
@@ -831,7 +1012,12 @@ class Node:
|
||||
): # unless a special channel index was used, we want to use the admin index
|
||||
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
||||
logging.debug(f"adminIndex:{adminIndex}")
|
||||
|
||||
if isinstance(self.nodeNum, int):
|
||||
nodeid = self.nodeNum
|
||||
else: # assume string starting with !
|
||||
nodeid = int(self.nodeNum[1:],16)
|
||||
if "adminSessionPassKey" in self.iface._getOrCreateByNum(nodeid):
|
||||
p.session_passkey = self.iface._getOrCreateByNum(nodeid).get("adminSessionPassKey")
|
||||
return self.iface.sendData(
|
||||
p,
|
||||
self.nodeNum,
|
||||
@@ -840,4 +1026,19 @@ class Node:
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=adminIndex,
|
||||
pkiEncrypted=True,
|
||||
)
|
||||
|
||||
def ensureSessionKey(self):
|
||||
"""If our entry in iface.nodesByNum doesn't already have an adminSessionPassKey, make a request to get one"""
|
||||
if self.noProto:
|
||||
logging.warning(
|
||||
f"Not ensuring session key, because protocol use is disabled by noProto"
|
||||
)
|
||||
else:
|
||||
if isinstance(self.nodeNum, int):
|
||||
nodeid = self.nodeNum
|
||||
else: # assume string starting with !
|
||||
nodeid = int(self.nodeNum[1:],16)
|
||||
if self.iface._getOrCreateByNum(nodeid).get("adminSessionPassKey") is None:
|
||||
self.requestConfig(admin_pb2.AdminMessage.SESSIONKEY_CONFIG)
|
||||
|
||||
25
meshtastic/protobuf/admin_pb2.py
generated
25
meshtastic/protobuf/admin_pb2.py
generated
File diff suppressed because one or more lines are too long
119
meshtastic/protobuf/admin_pb2.pyi
generated
119
meshtastic/protobuf/admin_pb2.pyi
generated
@@ -12,6 +12,7 @@ import google.protobuf.message
|
||||
import meshtastic.protobuf.channel_pb2
|
||||
import meshtastic.protobuf.config_pb2
|
||||
import meshtastic.protobuf.connection_status_pb2
|
||||
import meshtastic.protobuf.device_ui_pb2
|
||||
import meshtastic.protobuf.mesh_pb2
|
||||
import meshtastic.protobuf.module_config_pb2
|
||||
import sys
|
||||
@@ -68,6 +69,16 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
SECURITY_CONFIG: AdminMessage._ConfigType.ValueType # 7
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
SESSIONKEY_CONFIG: AdminMessage._ConfigType.ValueType # 8
|
||||
""""""
|
||||
DEVICEUI_CONFIG: AdminMessage._ConfigType.ValueType # 9
|
||||
"""
|
||||
device-ui config
|
||||
"""
|
||||
|
||||
class ConfigType(_ConfigType, metaclass=_ConfigTypeEnumTypeWrapper):
|
||||
"""
|
||||
@@ -102,6 +113,16 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
SECURITY_CONFIG: AdminMessage.ConfigType.ValueType # 7
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
SESSIONKEY_CONFIG: AdminMessage.ConfigType.ValueType # 8
|
||||
""""""
|
||||
DEVICEUI_CONFIG: AdminMessage.ConfigType.ValueType # 9
|
||||
"""
|
||||
device-ui config
|
||||
"""
|
||||
|
||||
class _ModuleConfigType:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
@@ -220,6 +241,32 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
TODO: REPLACE
|
||||
"""
|
||||
|
||||
class _BackupLocation:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _BackupLocationEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[AdminMessage._BackupLocation.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
FLASH: AdminMessage._BackupLocation.ValueType # 0
|
||||
"""
|
||||
Backup to the internal flash
|
||||
"""
|
||||
SD: AdminMessage._BackupLocation.ValueType # 1
|
||||
"""
|
||||
Backup to the SD card
|
||||
"""
|
||||
|
||||
class BackupLocation(_BackupLocation, metaclass=_BackupLocationEnumTypeWrapper): ...
|
||||
FLASH: AdminMessage.BackupLocation.ValueType # 0
|
||||
"""
|
||||
Backup to the internal flash
|
||||
"""
|
||||
SD: AdminMessage.BackupLocation.ValueType # 1
|
||||
"""
|
||||
Backup to the SD card
|
||||
"""
|
||||
|
||||
SESSION_PASSKEY_FIELD_NUMBER: builtins.int
|
||||
GET_CHANNEL_REQUEST_FIELD_NUMBER: builtins.int
|
||||
GET_CHANNEL_RESPONSE_FIELD_NUMBER: builtins.int
|
||||
GET_OWNER_REQUEST_FIELD_NUMBER: builtins.int
|
||||
@@ -242,6 +289,9 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
ENTER_DFU_MODE_REQUEST_FIELD_NUMBER: builtins.int
|
||||
DELETE_FILE_REQUEST_FIELD_NUMBER: builtins.int
|
||||
SET_SCALE_FIELD_NUMBER: builtins.int
|
||||
BACKUP_PREFERENCES_FIELD_NUMBER: builtins.int
|
||||
RESTORE_PREFERENCES_FIELD_NUMBER: builtins.int
|
||||
REMOVE_BACKUP_PREFERENCES_FIELD_NUMBER: builtins.int
|
||||
SET_OWNER_FIELD_NUMBER: builtins.int
|
||||
SET_CHANNEL_FIELD_NUMBER: builtins.int
|
||||
SET_CONFIG_FIELD_NUMBER: builtins.int
|
||||
@@ -253,6 +303,12 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
REMOVE_FAVORITE_NODE_FIELD_NUMBER: builtins.int
|
||||
SET_FIXED_POSITION_FIELD_NUMBER: builtins.int
|
||||
REMOVE_FIXED_POSITION_FIELD_NUMBER: builtins.int
|
||||
SET_TIME_ONLY_FIELD_NUMBER: builtins.int
|
||||
GET_UI_CONFIG_REQUEST_FIELD_NUMBER: builtins.int
|
||||
GET_UI_CONFIG_RESPONSE_FIELD_NUMBER: builtins.int
|
||||
STORE_UI_CONFIG_FIELD_NUMBER: builtins.int
|
||||
SET_IGNORED_NODE_FIELD_NUMBER: builtins.int
|
||||
REMOVE_IGNORED_NODE_FIELD_NUMBER: builtins.int
|
||||
BEGIN_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
|
||||
COMMIT_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
|
||||
FACTORY_RESET_DEVICE_FIELD_NUMBER: builtins.int
|
||||
@@ -262,6 +318,12 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
SHUTDOWN_SECONDS_FIELD_NUMBER: builtins.int
|
||||
FACTORY_RESET_CONFIG_FIELD_NUMBER: builtins.int
|
||||
NODEDB_RESET_FIELD_NUMBER: builtins.int
|
||||
session_passkey: builtins.bytes
|
||||
"""
|
||||
The node generates this key and sends it with any get_x_response packets.
|
||||
The client MUST include the same key with any set_x commands. Key expires after 300 seconds.
|
||||
Prevents replay attacks for admin messages.
|
||||
"""
|
||||
get_channel_request: builtins.int
|
||||
"""
|
||||
Send the specified channel in the response to this message
|
||||
@@ -320,6 +382,18 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
"""
|
||||
Set zero and offset for scale chips
|
||||
"""
|
||||
backup_preferences: global___AdminMessage.BackupLocation.ValueType
|
||||
"""
|
||||
Backup the node's preferences
|
||||
"""
|
||||
restore_preferences: global___AdminMessage.BackupLocation.ValueType
|
||||
"""
|
||||
Restore the node's preferences
|
||||
"""
|
||||
remove_backup_preferences: global___AdminMessage.BackupLocation.ValueType
|
||||
"""
|
||||
Remove backups of the node's preferences
|
||||
"""
|
||||
set_canned_message_module_messages: builtins.str
|
||||
"""
|
||||
Set the Canned Message Module messages text.
|
||||
@@ -344,6 +418,23 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
"""
|
||||
Clear fixed position coordinates and then set position.fixed_position = false
|
||||
"""
|
||||
set_time_only: builtins.int
|
||||
"""
|
||||
Set time only on the node
|
||||
Convenience method to set the time on the node (as Net quality) without any other position data
|
||||
"""
|
||||
get_ui_config_request: builtins.bool
|
||||
"""
|
||||
Tell the node to send the stored ui data.
|
||||
"""
|
||||
set_ignored_node: builtins.int
|
||||
"""
|
||||
Set specified node-num to be ignored on the NodeDB on the device
|
||||
"""
|
||||
remove_ignored_node: builtins.int
|
||||
"""
|
||||
Set specified node-num to be un-ignored on the NodeDB on the device
|
||||
"""
|
||||
begin_edit_settings: builtins.bool
|
||||
"""
|
||||
Begins an edit transaction for config, module config, owner, and channel settings changes
|
||||
@@ -465,9 +556,22 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
Set fixed position data on the node and then set the position.fixed_position = true
|
||||
"""
|
||||
|
||||
@property
|
||||
def get_ui_config_response(self) -> meshtastic.protobuf.device_ui_pb2.DeviceUIConfig:
|
||||
"""
|
||||
Reply stored device ui data.
|
||||
"""
|
||||
|
||||
@property
|
||||
def store_ui_config(self) -> meshtastic.protobuf.device_ui_pb2.DeviceUIConfig:
|
||||
"""
|
||||
Tell the node to store UI data persistently.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
session_passkey: builtins.bytes = ...,
|
||||
get_channel_request: builtins.int = ...,
|
||||
get_channel_response: meshtastic.protobuf.channel_pb2.Channel | None = ...,
|
||||
get_owner_request: builtins.bool = ...,
|
||||
@@ -490,6 +594,9 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
enter_dfu_mode_request: builtins.bool = ...,
|
||||
delete_file_request: builtins.str = ...,
|
||||
set_scale: builtins.int = ...,
|
||||
backup_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
|
||||
restore_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
|
||||
remove_backup_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
|
||||
set_owner: meshtastic.protobuf.mesh_pb2.User | None = ...,
|
||||
set_channel: meshtastic.protobuf.channel_pb2.Channel | None = ...,
|
||||
set_config: meshtastic.protobuf.config_pb2.Config | None = ...,
|
||||
@@ -501,6 +608,12 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
remove_favorite_node: builtins.int = ...,
|
||||
set_fixed_position: meshtastic.protobuf.mesh_pb2.Position | None = ...,
|
||||
remove_fixed_position: builtins.bool = ...,
|
||||
set_time_only: builtins.int = ...,
|
||||
get_ui_config_request: builtins.bool = ...,
|
||||
get_ui_config_response: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
|
||||
store_ui_config: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
|
||||
set_ignored_node: builtins.int = ...,
|
||||
remove_ignored_node: builtins.int = ...,
|
||||
begin_edit_settings: builtins.bool = ...,
|
||||
commit_edit_settings: builtins.bool = ...,
|
||||
factory_reset_device: builtins.int = ...,
|
||||
@@ -511,9 +624,9 @@ class AdminMessage(google.protobuf.message.Message):
|
||||
factory_reset_config: builtins.int = ...,
|
||||
nodedb_reset: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "shutdown_seconds", b"shutdown_seconds"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "shutdown_seconds", b"shutdown_seconds"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["get_channel_request", "get_channel_response", "get_owner_request", "get_owner_response", "get_config_request", "get_config_response", "get_module_config_request", "get_module_config_response", "get_canned_message_module_messages_request", "get_canned_message_module_messages_response", "get_device_metadata_request", "get_device_metadata_response", "get_ringtone_request", "get_ringtone_response", "get_device_connection_status_request", "get_device_connection_status_response", "set_ham_mode", "get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", "enter_dfu_mode_request", "delete_file_request", "set_scale", "set_owner", "set_channel", "set_config", "set_module_config", "set_canned_message_module_messages", "set_ringtone_message", "remove_by_nodenum", "set_favorite_node", "remove_favorite_node", "set_fixed_position", "remove_fixed_position", "begin_edit_settings", "commit_edit_settings", "factory_reset_device", "reboot_ota_seconds", "exit_simulator", "reboot_seconds", "shutdown_seconds", "factory_reset_config", "nodedb_reset"] | None: ...
|
||||
def HasField(self, field_name: typing.Literal["backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "session_passkey", b"session_passkey", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["get_channel_request", "get_channel_response", "get_owner_request", "get_owner_response", "get_config_request", "get_config_response", "get_module_config_request", "get_module_config_response", "get_canned_message_module_messages_request", "get_canned_message_module_messages_response", "get_device_metadata_request", "get_device_metadata_response", "get_ringtone_request", "get_ringtone_response", "get_device_connection_status_request", "get_device_connection_status_response", "set_ham_mode", "get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", "enter_dfu_mode_request", "delete_file_request", "set_scale", "backup_preferences", "restore_preferences", "remove_backup_preferences", "set_owner", "set_channel", "set_config", "set_module_config", "set_canned_message_module_messages", "set_ringtone_message", "remove_by_nodenum", "set_favorite_node", "remove_favorite_node", "set_fixed_position", "remove_fixed_position", "set_time_only", "get_ui_config_request", "get_ui_config_response", "store_ui_config", "set_ignored_node", "remove_ignored_node", "begin_edit_settings", "commit_edit_settings", "factory_reset_device", "reboot_ota_seconds", "exit_simulator", "reboot_seconds", "shutdown_seconds", "factory_reset_config", "nodedb_reset"] | None: ...
|
||||
|
||||
global___AdminMessage = AdminMessage
|
||||
|
||||
|
||||
32
meshtastic/protobuf/atak_pb2.py
generated
32
meshtastic/protobuf/atak_pb2.py
generated
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/atak.proto\x12\x13meshtastic.protobuf\"\x93\x02\n\tTAKPacket\x12\x15\n\ris_compressed\x18\x01 \x01(\x08\x12-\n\x07\x63ontact\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.Contact\x12)\n\x05group\x18\x03 \x01(\x0b\x32\x1a.meshtastic.protobuf.Group\x12+\n\x06status\x18\x04 \x01(\x0b\x32\x1b.meshtastic.protobuf.Status\x12\'\n\x03pli\x18\x05 \x01(\x0b\x32\x18.meshtastic.protobuf.PLIH\x00\x12,\n\x04\x63hat\x18\x06 \x01(\x0b\x32\x1c.meshtastic.protobuf.GeoChatH\x00\x42\x11\n\x0fpayload_variant\"\\\n\x07GeoChat\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0f\n\x02to\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0bto_callsign\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x05\n\x03_toB\x0e\n\x0c_to_callsign\"_\n\x05Group\x12-\n\x04role\x18\x01 \x01(\x0e\x32\x1f.meshtastic.protobuf.MemberRole\x12\'\n\x04team\x18\x02 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\"\x19\n\x06Status\x12\x0f\n\x07\x62\x61ttery\x18\x01 \x01(\r\"4\n\x07\x43ontact\x12\x10\n\x08\x63\x61llsign\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65vice_callsign\x18\x02 \x01(\t\"_\n\x03PLI\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\r\n\x05speed\x18\x04 \x01(\r\x12\x0e\n\x06\x63ourse\x18\x05 \x01(\r*\xc0\x01\n\x04Team\x12\x14\n\x10Unspecifed_Color\x10\x00\x12\t\n\x05White\x10\x01\x12\n\n\x06Yellow\x10\x02\x12\n\n\x06Orange\x10\x03\x12\x0b\n\x07Magenta\x10\x04\x12\x07\n\x03Red\x10\x05\x12\n\n\x06Maroon\x10\x06\x12\n\n\x06Purple\x10\x07\x12\r\n\tDark_Blue\x10\x08\x12\x08\n\x04\x42lue\x10\t\x12\x08\n\x04\x43yan\x10\n\x12\x08\n\x04Teal\x10\x0b\x12\t\n\x05Green\x10\x0c\x12\x0e\n\nDark_Green\x10\r\x12\t\n\x05\x42rown\x10\x0e*\x7f\n\nMemberRole\x12\x0e\n\nUnspecifed\x10\x00\x12\x0e\n\nTeamMember\x10\x01\x12\x0c\n\x08TeamLead\x10\x02\x12\x06\n\x02HQ\x10\x03\x12\n\n\x06Sniper\x10\x04\x12\t\n\x05Medic\x10\x05\x12\x13\n\x0f\x46orwardObserver\x10\x06\x12\x07\n\x03RTO\x10\x07\x12\x06\n\x02K9\x10\x08\x42_\n\x13\x63om.geeksville.meshB\nATAKProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/atak.proto\x12\x13meshtastic.protobuf\"\xa5\x02\n\tTAKPacket\x12\x15\n\ris_compressed\x18\x01 \x01(\x08\x12-\n\x07\x63ontact\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.Contact\x12)\n\x05group\x18\x03 \x01(\x0b\x32\x1a.meshtastic.protobuf.Group\x12+\n\x06status\x18\x04 \x01(\x0b\x32\x1b.meshtastic.protobuf.Status\x12\'\n\x03pli\x18\x05 \x01(\x0b\x32\x18.meshtastic.protobuf.PLIH\x00\x12,\n\x04\x63hat\x18\x06 \x01(\x0b\x32\x1c.meshtastic.protobuf.GeoChatH\x00\x12\x10\n\x06\x64\x65tail\x18\x07 \x01(\x0cH\x00\x42\x11\n\x0fpayload_variant\"\\\n\x07GeoChat\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0f\n\x02to\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0bto_callsign\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x05\n\x03_toB\x0e\n\x0c_to_callsign\"_\n\x05Group\x12-\n\x04role\x18\x01 \x01(\x0e\x32\x1f.meshtastic.protobuf.MemberRole\x12\'\n\x04team\x18\x02 \x01(\x0e\x32\x19.meshtastic.protobuf.Team\"\x19\n\x06Status\x12\x0f\n\x07\x62\x61ttery\x18\x01 \x01(\r\"4\n\x07\x43ontact\x12\x10\n\x08\x63\x61llsign\x18\x01 \x01(\t\x12\x17\n\x0f\x64\x65vice_callsign\x18\x02 \x01(\t\"_\n\x03PLI\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\r\n\x05speed\x18\x04 \x01(\r\x12\x0e\n\x06\x63ourse\x18\x05 \x01(\r*\xc0\x01\n\x04Team\x12\x14\n\x10Unspecifed_Color\x10\x00\x12\t\n\x05White\x10\x01\x12\n\n\x06Yellow\x10\x02\x12\n\n\x06Orange\x10\x03\x12\x0b\n\x07Magenta\x10\x04\x12\x07\n\x03Red\x10\x05\x12\n\n\x06Maroon\x10\x06\x12\n\n\x06Purple\x10\x07\x12\r\n\tDark_Blue\x10\x08\x12\x08\n\x04\x42lue\x10\t\x12\x08\n\x04\x43yan\x10\n\x12\x08\n\x04Teal\x10\x0b\x12\t\n\x05Green\x10\x0c\x12\x0e\n\nDark_Green\x10\r\x12\t\n\x05\x42rown\x10\x0e*\x7f\n\nMemberRole\x12\x0e\n\nUnspecifed\x10\x00\x12\x0e\n\nTeamMember\x10\x01\x12\x0c\n\x08TeamLead\x10\x02\x12\x06\n\x02HQ\x10\x03\x12\n\n\x06Sniper\x10\x04\x12\t\n\x05Medic\x10\x05\x12\x13\n\x0f\x46orwardObserver\x10\x06\x12\x07\n\x03RTO\x10\x07\x12\x06\n\x02K9\x10\x08\x42_\n\x13\x63om.geeksville.meshB\nATAKProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
@@ -21,20 +21,20 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.atak_pb
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nATAKProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_globals['_TEAM']._serialized_start=703
|
||||
_globals['_TEAM']._serialized_end=895
|
||||
_globals['_MEMBERROLE']._serialized_start=897
|
||||
_globals['_MEMBERROLE']._serialized_end=1024
|
||||
_globals['_TEAM']._serialized_start=721
|
||||
_globals['_TEAM']._serialized_end=913
|
||||
_globals['_MEMBERROLE']._serialized_start=915
|
||||
_globals['_MEMBERROLE']._serialized_end=1042
|
||||
_globals['_TAKPACKET']._serialized_start=56
|
||||
_globals['_TAKPACKET']._serialized_end=331
|
||||
_globals['_GEOCHAT']._serialized_start=333
|
||||
_globals['_GEOCHAT']._serialized_end=425
|
||||
_globals['_GROUP']._serialized_start=427
|
||||
_globals['_GROUP']._serialized_end=522
|
||||
_globals['_STATUS']._serialized_start=524
|
||||
_globals['_STATUS']._serialized_end=549
|
||||
_globals['_CONTACT']._serialized_start=551
|
||||
_globals['_CONTACT']._serialized_end=603
|
||||
_globals['_PLI']._serialized_start=605
|
||||
_globals['_PLI']._serialized_end=700
|
||||
_globals['_TAKPACKET']._serialized_end=349
|
||||
_globals['_GEOCHAT']._serialized_start=351
|
||||
_globals['_GEOCHAT']._serialized_end=443
|
||||
_globals['_GROUP']._serialized_start=445
|
||||
_globals['_GROUP']._serialized_end=540
|
||||
_globals['_STATUS']._serialized_start=542
|
||||
_globals['_STATUS']._serialized_end=567
|
||||
_globals['_CONTACT']._serialized_start=569
|
||||
_globals['_CONTACT']._serialized_end=621
|
||||
_globals['_PLI']._serialized_start=623
|
||||
_globals['_PLI']._serialized_end=718
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
||||
13
meshtastic/protobuf/atak_pb2.pyi
generated
13
meshtastic/protobuf/atak_pb2.pyi
generated
@@ -248,10 +248,16 @@ class TAKPacket(google.protobuf.message.Message):
|
||||
STATUS_FIELD_NUMBER: builtins.int
|
||||
PLI_FIELD_NUMBER: builtins.int
|
||||
CHAT_FIELD_NUMBER: builtins.int
|
||||
DETAIL_FIELD_NUMBER: builtins.int
|
||||
is_compressed: builtins.bool
|
||||
"""
|
||||
Are the payloads strings compressed for LoRA transport?
|
||||
"""
|
||||
detail: builtins.bytes
|
||||
"""
|
||||
Generic CoT detail XML
|
||||
May be compressed / truncated by the sender (EUD)
|
||||
"""
|
||||
@property
|
||||
def contact(self) -> global___Contact:
|
||||
"""
|
||||
@@ -291,10 +297,11 @@ class TAKPacket(google.protobuf.message.Message):
|
||||
status: global___Status | None = ...,
|
||||
pli: global___PLI | None = ...,
|
||||
chat: global___GeoChat | None = ...,
|
||||
detail: builtins.bytes = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["chat", b"chat", "contact", b"contact", "group", b"group", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["chat", b"chat", "contact", b"contact", "group", b"group", "is_compressed", b"is_compressed", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["pli", "chat"] | None: ...
|
||||
def HasField(self, field_name: typing.Literal["chat", b"chat", "contact", b"contact", "detail", b"detail", "group", b"group", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["chat", b"chat", "contact", b"contact", "detail", b"detail", "group", b"group", "is_compressed", b"is_compressed", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["pli", "chat", "detail"] | None: ...
|
||||
|
||||
global___TAKPacket = TAKPacket
|
||||
|
||||
|
||||
7
meshtastic/protobuf/clientonly_pb2.py
generated
7
meshtastic/protobuf/clientonly_pb2.py
generated
@@ -12,9 +12,10 @@ _sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
|
||||
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/clientonly.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/localonly.proto\"\x9f\x02\n\rDeviceProfile\x12\x16\n\tlong_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nshort_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63hannel_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x35\n\x06\x63onfig\x18\x04 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfigH\x03\x88\x01\x01\x12\x42\n\rmodule_config\x18\x05 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfigH\x04\x88\x01\x01\x42\x0c\n\n_long_nameB\r\n\x0b_short_nameB\x0e\n\x0c_channel_urlB\t\n\x07_configB\x10\n\x0e_module_configBe\n\x13\x63om.geeksville.meshB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/clientonly.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\"\xc4\x03\n\rDeviceProfile\x12\x16\n\tlong_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nshort_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63hannel_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x35\n\x06\x63onfig\x18\x04 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfigH\x03\x88\x01\x01\x12\x42\n\rmodule_config\x18\x05 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfigH\x04\x88\x01\x01\x12:\n\x0e\x66ixed_position\x18\x06 \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x05\x88\x01\x01\x12\x15\n\x08ringtone\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1c\n\x0f\x63\x61nned_messages\x18\x08 \x01(\tH\x07\x88\x01\x01\x42\x0c\n\n_long_nameB\r\n\x0b_short_nameB\x0e\n\x0c_channel_urlB\t\n\x07_configB\x10\n\x0e_module_configB\x11\n\x0f_fixed_positionB\x0b\n\t_ringtoneB\x12\n\x10_canned_messagesBe\n\x13\x63om.geeksville.meshB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
@@ -22,6 +23,6 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.cliento
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\020ClientOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_globals['_DEVICEPROFILE']._serialized_start=99
|
||||
_globals['_DEVICEPROFILE']._serialized_end=386
|
||||
_globals['_DEVICEPROFILE']._serialized_start=131
|
||||
_globals['_DEVICEPROFILE']._serialized_end=583
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
||||
31
meshtastic/protobuf/clientonly_pb2.pyi
generated
31
meshtastic/protobuf/clientonly_pb2.pyi
generated
@@ -7,6 +7,7 @@ import builtins
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.message
|
||||
import meshtastic.protobuf.localonly_pb2
|
||||
import meshtastic.protobuf.mesh_pb2
|
||||
import typing
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
@@ -25,6 +26,9 @@ class DeviceProfile(google.protobuf.message.Message):
|
||||
CHANNEL_URL_FIELD_NUMBER: builtins.int
|
||||
CONFIG_FIELD_NUMBER: builtins.int
|
||||
MODULE_CONFIG_FIELD_NUMBER: builtins.int
|
||||
FIXED_POSITION_FIELD_NUMBER: builtins.int
|
||||
RINGTONE_FIELD_NUMBER: builtins.int
|
||||
CANNED_MESSAGES_FIELD_NUMBER: builtins.int
|
||||
long_name: builtins.str
|
||||
"""
|
||||
Long name for the node
|
||||
@@ -37,6 +41,14 @@ class DeviceProfile(google.protobuf.message.Message):
|
||||
"""
|
||||
The url of the channels from our node
|
||||
"""
|
||||
ringtone: builtins.str
|
||||
"""
|
||||
Ringtone for ExternalNotification
|
||||
"""
|
||||
canned_messages: builtins.str
|
||||
"""
|
||||
Predefined messages for CannedMessage
|
||||
"""
|
||||
@property
|
||||
def config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig:
|
||||
"""
|
||||
@@ -49,6 +61,12 @@ class DeviceProfile(google.protobuf.message.Message):
|
||||
The ModuleConfig of the node
|
||||
"""
|
||||
|
||||
@property
|
||||
def fixed_position(self) -> meshtastic.protobuf.mesh_pb2.Position:
|
||||
"""
|
||||
Fixed position data
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -57,18 +75,27 @@ class DeviceProfile(google.protobuf.message.Message):
|
||||
channel_url: builtins.str | None = ...,
|
||||
config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ...,
|
||||
module_config: meshtastic.protobuf.localonly_pb2.LocalModuleConfig | None = ...,
|
||||
fixed_position: meshtastic.protobuf.mesh_pb2.Position | None = ...,
|
||||
ringtone: builtins.str | None = ...,
|
||||
canned_messages: builtins.str | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_channel_url", b"_channel_url", "_config", b"_config", "_long_name", b"_long_name", "_module_config", b"_module_config", "_short_name", b"_short_name", "channel_url", b"channel_url", "config", b"config", "long_name", b"long_name", "module_config", b"module_config", "short_name", b"short_name"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_channel_url", b"_channel_url", "_config", b"_config", "_long_name", b"_long_name", "_module_config", b"_module_config", "_short_name", b"_short_name", "channel_url", b"channel_url", "config", b"config", "long_name", b"long_name", "module_config", b"module_config", "short_name", b"short_name"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_canned_messages", b"_canned_messages", "_channel_url", b"_channel_url", "_config", b"_config", "_fixed_position", b"_fixed_position", "_long_name", b"_long_name", "_module_config", b"_module_config", "_ringtone", b"_ringtone", "_short_name", b"_short_name", "canned_messages", b"canned_messages", "channel_url", b"channel_url", "config", b"config", "fixed_position", b"fixed_position", "long_name", b"long_name", "module_config", b"module_config", "ringtone", b"ringtone", "short_name", b"short_name"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_canned_messages", b"_canned_messages", "_channel_url", b"_channel_url", "_config", b"_config", "_fixed_position", b"_fixed_position", "_long_name", b"_long_name", "_module_config", b"_module_config", "_ringtone", b"_ringtone", "_short_name", b"_short_name", "canned_messages", b"canned_messages", "channel_url", b"channel_url", "config", b"config", "fixed_position", b"fixed_position", "long_name", b"long_name", "module_config", b"module_config", "ringtone", b"ringtone", "short_name", b"short_name"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_canned_messages", b"_canned_messages"]) -> typing.Literal["canned_messages"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_channel_url", b"_channel_url"]) -> typing.Literal["channel_url"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_config", b"_config"]) -> typing.Literal["config"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_fixed_position", b"_fixed_position"]) -> typing.Literal["fixed_position"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_long_name", b"_long_name"]) -> typing.Literal["long_name"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_module_config", b"_module_config"]) -> typing.Literal["module_config"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ringtone", b"_ringtone"]) -> typing.Literal["ringtone"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_short_name", b"_short_name"]) -> typing.Literal["short_name"] | None: ...
|
||||
|
||||
global___DeviceProfile = DeviceProfile
|
||||
|
||||
103
meshtastic/protobuf/config_pb2.py
generated
103
meshtastic/protobuf/config_pb2.py
generated
File diff suppressed because one or more lines are too long
234
meshtastic/protobuf/config_pb2.pyi
generated
234
meshtastic/protobuf/config_pb2.pyi
generated
@@ -9,6 +9,7 @@ import google.protobuf.descriptor
|
||||
import google.protobuf.internal.containers
|
||||
import google.protobuf.internal.enum_type_wrapper
|
||||
import google.protobuf.message
|
||||
import meshtastic.protobuf.device_ui_pb2
|
||||
import sys
|
||||
import typing
|
||||
|
||||
@@ -107,6 +108,14 @@ class Config(google.protobuf.message.Message):
|
||||
and automatic TAK PLI (position location information) broadcasts.
|
||||
Uses position module configuration to determine TAK PLI broadcast interval.
|
||||
"""
|
||||
ROUTER_LATE: Config.DeviceConfig._Role.ValueType # 11
|
||||
"""
|
||||
Description: Will always rebroadcast packets, but will do so after all other modes.
|
||||
Technical Details: Used for router nodes that are intended to provide additional coverage
|
||||
in areas not already covered by other routers, or to bridge around problematic terrain,
|
||||
but should not be given priority over other routers in order to avoid unnecessaraily
|
||||
consuming hops.
|
||||
"""
|
||||
|
||||
class Role(_Role, metaclass=_RoleEnumTypeWrapper):
|
||||
"""
|
||||
@@ -183,6 +192,14 @@ class Config(google.protobuf.message.Message):
|
||||
and automatic TAK PLI (position location information) broadcasts.
|
||||
Uses position module configuration to determine TAK PLI broadcast interval.
|
||||
"""
|
||||
ROUTER_LATE: Config.DeviceConfig.Role.ValueType # 11
|
||||
"""
|
||||
Description: Will always rebroadcast packets, but will do so after all other modes.
|
||||
Technical Details: Used for router nodes that are intended to provide additional coverage
|
||||
in areas not already covered by other routers, or to bridge around problematic terrain,
|
||||
but should not be given priority over other routers in order to avoid unnecessaraily
|
||||
consuming hops.
|
||||
"""
|
||||
|
||||
class _RebroadcastMode:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
@@ -210,6 +227,15 @@ class Config(google.protobuf.message.Message):
|
||||
Ignores observed messages from foreign meshes like LOCAL_ONLY,
|
||||
but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB)
|
||||
"""
|
||||
NONE: Config.DeviceConfig._RebroadcastMode.ValueType # 4
|
||||
"""
|
||||
Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role.
|
||||
"""
|
||||
CORE_PORTNUMS_ONLY: Config.DeviceConfig._RebroadcastMode.ValueType # 5
|
||||
"""
|
||||
Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc.
|
||||
Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing.
|
||||
"""
|
||||
|
||||
class RebroadcastMode(_RebroadcastMode, metaclass=_RebroadcastModeEnumTypeWrapper):
|
||||
"""
|
||||
@@ -236,10 +262,18 @@ class Config(google.protobuf.message.Message):
|
||||
Ignores observed messages from foreign meshes like LOCAL_ONLY,
|
||||
but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB)
|
||||
"""
|
||||
NONE: Config.DeviceConfig.RebroadcastMode.ValueType # 4
|
||||
"""
|
||||
Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role.
|
||||
"""
|
||||
CORE_PORTNUMS_ONLY: Config.DeviceConfig.RebroadcastMode.ValueType # 5
|
||||
"""
|
||||
Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc.
|
||||
Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing.
|
||||
"""
|
||||
|
||||
ROLE_FIELD_NUMBER: builtins.int
|
||||
SERIAL_ENABLED_FIELD_NUMBER: builtins.int
|
||||
DEBUG_LOG_ENABLED_FIELD_NUMBER: builtins.int
|
||||
BUTTON_GPIO_FIELD_NUMBER: builtins.int
|
||||
BUZZER_GPIO_FIELD_NUMBER: builtins.int
|
||||
REBROADCAST_MODE_FIELD_NUMBER: builtins.int
|
||||
@@ -256,11 +290,7 @@ class Config(google.protobuf.message.Message):
|
||||
serial_enabled: builtins.bool
|
||||
"""
|
||||
Disabling this will disable the SerialConsole by not initilizing the StreamAPI
|
||||
"""
|
||||
debug_log_enabled: builtins.bool
|
||||
"""
|
||||
By default we turn off logging as soon as an API client connects (to keep shared serial link quiet).
|
||||
Set this to true to leave the debug log outputting even when API is active.
|
||||
Moved to SecurityConfig
|
||||
"""
|
||||
button_gpio: builtins.int
|
||||
"""
|
||||
@@ -289,6 +319,7 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
If true, device is considered to be "managed" by a mesh administrator
|
||||
Clients should then limit available configuration and administrative options inside the user interface
|
||||
Moved to SecurityConfig
|
||||
"""
|
||||
disable_triple_click: builtins.bool
|
||||
"""
|
||||
@@ -307,7 +338,6 @@ class Config(google.protobuf.message.Message):
|
||||
*,
|
||||
role: global___Config.DeviceConfig.Role.ValueType = ...,
|
||||
serial_enabled: builtins.bool = ...,
|
||||
debug_log_enabled: builtins.bool = ...,
|
||||
button_gpio: builtins.int = ...,
|
||||
buzzer_gpio: builtins.int = ...,
|
||||
rebroadcast_mode: global___Config.DeviceConfig.RebroadcastMode.ValueType = ...,
|
||||
@@ -318,7 +348,7 @@ class Config(google.protobuf.message.Message):
|
||||
tzdef: builtins.str = ...,
|
||||
led_heartbeat_disabled: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["button_gpio", b"button_gpio", "buzzer_gpio", b"buzzer_gpio", "debug_log_enabled", b"debug_log_enabled", "disable_triple_click", b"disable_triple_click", "double_tap_as_button_press", b"double_tap_as_button_press", "is_managed", b"is_managed", "led_heartbeat_disabled", b"led_heartbeat_disabled", "node_info_broadcast_secs", b"node_info_broadcast_secs", "rebroadcast_mode", b"rebroadcast_mode", "role", b"role", "serial_enabled", b"serial_enabled", "tzdef", b"tzdef"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["button_gpio", b"button_gpio", "buzzer_gpio", b"buzzer_gpio", "disable_triple_click", b"disable_triple_click", "double_tap_as_button_press", b"double_tap_as_button_press", "is_managed", b"is_managed", "led_heartbeat_disabled", b"led_heartbeat_disabled", "node_info_broadcast_secs", b"node_info_broadcast_secs", "rebroadcast_mode", b"rebroadcast_mode", "role", b"role", "serial_enabled", b"serial_enabled", "tzdef", b"tzdef"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class PositionConfig(google.protobuf.message.Message):
|
||||
@@ -679,6 +709,35 @@ class Config(google.protobuf.message.Message):
|
||||
use static ip address
|
||||
"""
|
||||
|
||||
class _ProtocolFlags:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _ProtocolFlagsEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Config.NetworkConfig._ProtocolFlags.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
NO_BROADCAST: Config.NetworkConfig._ProtocolFlags.ValueType # 0
|
||||
"""
|
||||
Do not broadcast packets over any network protocol
|
||||
"""
|
||||
UDP_BROADCAST: Config.NetworkConfig._ProtocolFlags.ValueType # 1
|
||||
"""
|
||||
Enable broadcasting packets via UDP over the local network
|
||||
"""
|
||||
|
||||
class ProtocolFlags(_ProtocolFlags, metaclass=_ProtocolFlagsEnumTypeWrapper):
|
||||
"""
|
||||
Available flags auxiliary network protocols
|
||||
"""
|
||||
|
||||
NO_BROADCAST: Config.NetworkConfig.ProtocolFlags.ValueType # 0
|
||||
"""
|
||||
Do not broadcast packets over any network protocol
|
||||
"""
|
||||
UDP_BROADCAST: Config.NetworkConfig.ProtocolFlags.ValueType # 1
|
||||
"""
|
||||
Enable broadcasting packets via UDP over the local network
|
||||
"""
|
||||
|
||||
@typing.final
|
||||
class IpV4Config(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
@@ -721,6 +780,7 @@ class Config(google.protobuf.message.Message):
|
||||
ADDRESS_MODE_FIELD_NUMBER: builtins.int
|
||||
IPV4_CONFIG_FIELD_NUMBER: builtins.int
|
||||
RSYSLOG_SERVER_FIELD_NUMBER: builtins.int
|
||||
ENABLED_PROTOCOLS_FIELD_NUMBER: builtins.int
|
||||
wifi_enabled: builtins.bool
|
||||
"""
|
||||
Enable WiFi (disables Bluetooth)
|
||||
@@ -750,6 +810,10 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
rsyslog Server and Port
|
||||
"""
|
||||
enabled_protocols: builtins.int
|
||||
"""
|
||||
Flags for enabling/disabling network protocols
|
||||
"""
|
||||
@property
|
||||
def ipv4_config(self) -> global___Config.NetworkConfig.IpV4Config:
|
||||
"""
|
||||
@@ -767,9 +831,10 @@ class Config(google.protobuf.message.Message):
|
||||
address_mode: global___Config.NetworkConfig.AddressMode.ValueType = ...,
|
||||
ipv4_config: global___Config.NetworkConfig.IpV4Config | None = ...,
|
||||
rsyslog_server: builtins.str = ...,
|
||||
enabled_protocols: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["ipv4_config", b"ipv4_config"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["address_mode", b"address_mode", "eth_enabled", b"eth_enabled", "ipv4_config", b"ipv4_config", "ntp_server", b"ntp_server", "rsyslog_server", b"rsyslog_server", "wifi_enabled", b"wifi_enabled", "wifi_psk", b"wifi_psk", "wifi_ssid", b"wifi_ssid"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["address_mode", b"address_mode", "enabled_protocols", b"enabled_protocols", "eth_enabled", b"eth_enabled", "ipv4_config", b"ipv4_config", "ntp_server", b"ntp_server", "rsyslog_server", b"rsyslog_server", "wifi_enabled", b"wifi_enabled", "wifi_psk", b"wifi_psk", "wifi_ssid", b"wifi_ssid"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class DisplayConfig(google.protobuf.message.Message):
|
||||
@@ -1053,6 +1118,7 @@ class Config(google.protobuf.message.Message):
|
||||
HEADING_BOLD_FIELD_NUMBER: builtins.int
|
||||
WAKE_ON_TAP_OR_MOTION_FIELD_NUMBER: builtins.int
|
||||
COMPASS_ORIENTATION_FIELD_NUMBER: builtins.int
|
||||
USE_12H_CLOCK_FIELD_NUMBER: builtins.int
|
||||
screen_on_secs: builtins.int
|
||||
"""
|
||||
Number of seconds the screen stays on after pressing the user button or receiving a message
|
||||
@@ -1100,6 +1166,11 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Indicates how to rotate or invert the compass output to accurate display on the display.
|
||||
"""
|
||||
use_12h_clock: builtins.bool
|
||||
"""
|
||||
If false (default), the device will display the time in 24-hour format on screen.
|
||||
If true, the device will display the time in 12-hour format on screen.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -1114,8 +1185,9 @@ class Config(google.protobuf.message.Message):
|
||||
heading_bold: builtins.bool = ...,
|
||||
wake_on_tap_or_motion: builtins.bool = ...,
|
||||
compass_orientation: global___Config.DisplayConfig.CompassOrientation.ValueType = ...,
|
||||
use_12h_clock: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["auto_screen_carousel_secs", b"auto_screen_carousel_secs", "compass_north_top", b"compass_north_top", "compass_orientation", b"compass_orientation", "displaymode", b"displaymode", "flip_screen", b"flip_screen", "gps_format", b"gps_format", "heading_bold", b"heading_bold", "oled", b"oled", "screen_on_secs", b"screen_on_secs", "units", b"units", "wake_on_tap_or_motion", b"wake_on_tap_or_motion"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["auto_screen_carousel_secs", b"auto_screen_carousel_secs", "compass_north_top", b"compass_north_top", "compass_orientation", b"compass_orientation", "displaymode", b"displaymode", "flip_screen", b"flip_screen", "gps_format", b"gps_format", "heading_bold", b"heading_bold", "oled", b"oled", "screen_on_secs", b"screen_on_secs", "units", b"units", "use_12h_clock", b"use_12h_clock", "wake_on_tap_or_motion", b"wake_on_tap_or_motion"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class LoRaConfig(google.protobuf.message.Message):
|
||||
@@ -1207,6 +1279,18 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Singapore 923mhz
|
||||
"""
|
||||
PH_433: Config.LoRaConfig._RegionCode.ValueType # 19
|
||||
"""
|
||||
Philippines 433mhz
|
||||
"""
|
||||
PH_868: Config.LoRaConfig._RegionCode.ValueType # 20
|
||||
"""
|
||||
Philippines 868mhz
|
||||
"""
|
||||
PH_915: Config.LoRaConfig._RegionCode.ValueType # 21
|
||||
"""
|
||||
Philippines 915mhz
|
||||
"""
|
||||
|
||||
class RegionCode(_RegionCode, metaclass=_RegionCodeEnumTypeWrapper): ...
|
||||
UNSET: Config.LoRaConfig.RegionCode.ValueType # 0
|
||||
@@ -1285,6 +1369,18 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Singapore 923mhz
|
||||
"""
|
||||
PH_433: Config.LoRaConfig.RegionCode.ValueType # 19
|
||||
"""
|
||||
Philippines 433mhz
|
||||
"""
|
||||
PH_868: Config.LoRaConfig.RegionCode.ValueType # 20
|
||||
"""
|
||||
Philippines 868mhz
|
||||
"""
|
||||
PH_915: Config.LoRaConfig.RegionCode.ValueType # 21
|
||||
"""
|
||||
Philippines 915mhz
|
||||
"""
|
||||
|
||||
class _ModemPreset:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
@@ -1303,6 +1399,7 @@ class Config(google.protobuf.message.Message):
|
||||
VERY_LONG_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 2
|
||||
"""
|
||||
Very Long Range - Slow
|
||||
Deprecated in 2.5: Works only with txco and is unusably slow
|
||||
"""
|
||||
MEDIUM_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 3
|
||||
"""
|
||||
@@ -1324,6 +1421,12 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Long Range - Moderately Fast
|
||||
"""
|
||||
SHORT_TURBO: Config.LoRaConfig._ModemPreset.ValueType # 8
|
||||
"""
|
||||
Short Range - Turbo
|
||||
This is the fastest preset and the only one with 500kHz bandwidth.
|
||||
It is not legal to use in all regions due to this wider bandwidth.
|
||||
"""
|
||||
|
||||
class ModemPreset(_ModemPreset, metaclass=_ModemPresetEnumTypeWrapper):
|
||||
"""
|
||||
@@ -1342,6 +1445,7 @@ class Config(google.protobuf.message.Message):
|
||||
VERY_LONG_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 2
|
||||
"""
|
||||
Very Long Range - Slow
|
||||
Deprecated in 2.5: Works only with txco and is unusably slow
|
||||
"""
|
||||
MEDIUM_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 3
|
||||
"""
|
||||
@@ -1363,6 +1467,12 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Long Range - Moderately Fast
|
||||
"""
|
||||
SHORT_TURBO: Config.LoRaConfig.ModemPreset.ValueType # 8
|
||||
"""
|
||||
Short Range - Turbo
|
||||
This is the fastest preset and the only one with 500kHz bandwidth.
|
||||
It is not legal to use in all regions due to this wider bandwidth.
|
||||
"""
|
||||
|
||||
USE_PRESET_FIELD_NUMBER: builtins.int
|
||||
MODEM_PRESET_FIELD_NUMBER: builtins.int
|
||||
@@ -1381,6 +1491,7 @@ class Config(google.protobuf.message.Message):
|
||||
PA_FAN_DISABLED_FIELD_NUMBER: builtins.int
|
||||
IGNORE_INCOMING_FIELD_NUMBER: builtins.int
|
||||
IGNORE_MQTT_FIELD_NUMBER: builtins.int
|
||||
CONFIG_OK_TO_MQTT_FIELD_NUMBER: builtins.int
|
||||
use_preset: builtins.bool
|
||||
"""
|
||||
When enabled, the `modem_preset` fields will be adhered to, else the `bandwidth`/`spread_factor`/`coding_rate`
|
||||
@@ -1474,6 +1585,10 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
If true, the device will not process any packets received via LoRa that passed via MQTT anywhere on the path towards it.
|
||||
"""
|
||||
config_ok_to_mqtt: builtins.bool
|
||||
"""
|
||||
Sets the ok_to_mqtt bit on outgoing packets
|
||||
"""
|
||||
@property
|
||||
def ignore_incoming(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]:
|
||||
"""
|
||||
@@ -1502,8 +1617,9 @@ class Config(google.protobuf.message.Message):
|
||||
pa_fan_disabled: builtins.bool = ...,
|
||||
ignore_incoming: collections.abc.Iterable[builtins.int] | None = ...,
|
||||
ignore_mqtt: builtins.bool = ...,
|
||||
config_ok_to_mqtt: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["bandwidth", b"bandwidth", "channel_num", b"channel_num", "coding_rate", b"coding_rate", "frequency_offset", b"frequency_offset", "hop_limit", b"hop_limit", "ignore_incoming", b"ignore_incoming", "ignore_mqtt", b"ignore_mqtt", "modem_preset", b"modem_preset", "override_duty_cycle", b"override_duty_cycle", "override_frequency", b"override_frequency", "pa_fan_disabled", b"pa_fan_disabled", "region", b"region", "spread_factor", b"spread_factor", "sx126x_rx_boosted_gain", b"sx126x_rx_boosted_gain", "tx_enabled", b"tx_enabled", "tx_power", b"tx_power", "use_preset", b"use_preset"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["bandwidth", b"bandwidth", "channel_num", b"channel_num", "coding_rate", b"coding_rate", "config_ok_to_mqtt", b"config_ok_to_mqtt", "frequency_offset", b"frequency_offset", "hop_limit", b"hop_limit", "ignore_incoming", b"ignore_incoming", "ignore_mqtt", b"ignore_mqtt", "modem_preset", b"modem_preset", "override_duty_cycle", b"override_duty_cycle", "override_frequency", b"override_frequency", "pa_fan_disabled", b"pa_fan_disabled", "region", b"region", "spread_factor", b"spread_factor", "sx126x_rx_boosted_gain", b"sx126x_rx_boosted_gain", "tx_enabled", b"tx_enabled", "tx_power", b"tx_power", "use_preset", b"use_preset"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class BluetoothConfig(google.protobuf.message.Message):
|
||||
@@ -1545,7 +1661,6 @@ class Config(google.protobuf.message.Message):
|
||||
ENABLED_FIELD_NUMBER: builtins.int
|
||||
MODE_FIELD_NUMBER: builtins.int
|
||||
FIXED_PIN_FIELD_NUMBER: builtins.int
|
||||
DEVICE_LOGGING_ENABLED_FIELD_NUMBER: builtins.int
|
||||
enabled: builtins.bool
|
||||
"""
|
||||
Enable Bluetooth on the device
|
||||
@@ -1558,19 +1673,84 @@ class Config(google.protobuf.message.Message):
|
||||
"""
|
||||
Specified PIN for PairingMode.FixedPin
|
||||
"""
|
||||
device_logging_enabled: builtins.bool
|
||||
"""
|
||||
Enables device (serial style logs) over Bluetooth
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
enabled: builtins.bool = ...,
|
||||
mode: global___Config.BluetoothConfig.PairingMode.ValueType = ...,
|
||||
fixed_pin: builtins.int = ...,
|
||||
device_logging_enabled: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["device_logging_enabled", b"device_logging_enabled", "enabled", b"enabled", "fixed_pin", b"fixed_pin", "mode", b"mode"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["enabled", b"enabled", "fixed_pin", b"fixed_pin", "mode", b"mode"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class SecurityConfig(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
PUBLIC_KEY_FIELD_NUMBER: builtins.int
|
||||
PRIVATE_KEY_FIELD_NUMBER: builtins.int
|
||||
ADMIN_KEY_FIELD_NUMBER: builtins.int
|
||||
IS_MANAGED_FIELD_NUMBER: builtins.int
|
||||
SERIAL_ENABLED_FIELD_NUMBER: builtins.int
|
||||
DEBUG_LOG_API_ENABLED_FIELD_NUMBER: builtins.int
|
||||
ADMIN_CHANNEL_ENABLED_FIELD_NUMBER: builtins.int
|
||||
public_key: builtins.bytes
|
||||
"""
|
||||
The public key of the user's device.
|
||||
Sent out to other nodes on the mesh to allow them to compute a shared secret key.
|
||||
"""
|
||||
private_key: builtins.bytes
|
||||
"""
|
||||
The private key of the device.
|
||||
Used to create a shared key with a remote device.
|
||||
"""
|
||||
is_managed: builtins.bool
|
||||
"""
|
||||
If true, device is considered to be "managed" by a mesh administrator via admin messages
|
||||
Device is managed by a mesh administrator.
|
||||
"""
|
||||
serial_enabled: builtins.bool
|
||||
"""
|
||||
Serial Console over the Stream API."
|
||||
"""
|
||||
debug_log_api_enabled: builtins.bool
|
||||
"""
|
||||
By default we turn off logging as soon as an API client connects (to keep shared serial link quiet).
|
||||
Output live debug logging over serial or bluetooth is set to true.
|
||||
"""
|
||||
admin_channel_enabled: builtins.bool
|
||||
"""
|
||||
Allow incoming device control over the insecure legacy admin channel.
|
||||
"""
|
||||
@property
|
||||
def admin_key(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]:
|
||||
"""
|
||||
The public key authorized to send admin messages to this node.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
public_key: builtins.bytes = ...,
|
||||
private_key: builtins.bytes = ...,
|
||||
admin_key: collections.abc.Iterable[builtins.bytes] | None = ...,
|
||||
is_managed: builtins.bool = ...,
|
||||
serial_enabled: builtins.bool = ...,
|
||||
debug_log_api_enabled: builtins.bool = ...,
|
||||
admin_channel_enabled: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["admin_channel_enabled", b"admin_channel_enabled", "admin_key", b"admin_key", "debug_log_api_enabled", b"debug_log_api_enabled", "is_managed", b"is_managed", "private_key", b"private_key", "public_key", b"public_key", "serial_enabled", b"serial_enabled"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class SessionkeyConfig(google.protobuf.message.Message):
|
||||
"""
|
||||
Blank config request, strictly for getting the session key
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
) -> None: ...
|
||||
|
||||
DEVICE_FIELD_NUMBER: builtins.int
|
||||
POSITION_FIELD_NUMBER: builtins.int
|
||||
@@ -1579,6 +1759,9 @@ class Config(google.protobuf.message.Message):
|
||||
DISPLAY_FIELD_NUMBER: builtins.int
|
||||
LORA_FIELD_NUMBER: builtins.int
|
||||
BLUETOOTH_FIELD_NUMBER: builtins.int
|
||||
SECURITY_FIELD_NUMBER: builtins.int
|
||||
SESSIONKEY_FIELD_NUMBER: builtins.int
|
||||
DEVICE_UI_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def device(self) -> global___Config.DeviceConfig: ...
|
||||
@property
|
||||
@@ -1593,6 +1776,12 @@ class Config(google.protobuf.message.Message):
|
||||
def lora(self) -> global___Config.LoRaConfig: ...
|
||||
@property
|
||||
def bluetooth(self) -> global___Config.BluetoothConfig: ...
|
||||
@property
|
||||
def security(self) -> global___Config.SecurityConfig: ...
|
||||
@property
|
||||
def sessionkey(self) -> global___Config.SessionkeyConfig: ...
|
||||
@property
|
||||
def device_ui(self) -> meshtastic.protobuf.device_ui_pb2.DeviceUIConfig: ...
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -1603,9 +1792,12 @@ class Config(google.protobuf.message.Message):
|
||||
display: global___Config.DisplayConfig | None = ...,
|
||||
lora: global___Config.LoRaConfig | None = ...,
|
||||
bluetooth: global___Config.BluetoothConfig | None = ...,
|
||||
security: global___Config.SecurityConfig | None = ...,
|
||||
sessionkey: global___Config.SessionkeyConfig | None = ...,
|
||||
device_ui: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "payload_variant", b"payload_variant", "position", b"position", "power", b"power"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "payload_variant", b"payload_variant", "position", b"position", "power", b"power"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["device", "position", "power", "network", "display", "lora", "bluetooth"] | None: ...
|
||||
def HasField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "device_ui", b"device_ui", "display", b"display", "lora", b"lora", "network", b"network", "payload_variant", b"payload_variant", "position", b"position", "power", b"power", "security", b"security", "sessionkey", b"sessionkey"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "device_ui", b"device_ui", "display", b"display", "lora", b"lora", "network", b"network", "payload_variant", b"payload_variant", "position", b"position", "power", b"power", "security", b"security", "sessionkey", b"sessionkey"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["device", "position", "power", "network", "display", "lora", "bluetooth", "security", "sessionkey", "device_ui"] | None: ...
|
||||
|
||||
global___Config = Config
|
||||
|
||||
38
meshtastic/protobuf/device_ui_pb2.py
generated
Normal file
38
meshtastic/protobuf/device_ui_pb2.py
generated
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: meshtastic/protobuf/device_ui.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/device_ui.proto\x12\x13meshtastic.protobuf\"\xeb\x03\n\x0e\x44\x65viceUIConfig\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x19\n\x11screen_brightness\x18\x02 \x01(\r\x12\x16\n\x0escreen_timeout\x18\x03 \x01(\r\x12\x13\n\x0bscreen_lock\x18\x04 \x01(\x08\x12\x15\n\rsettings_lock\x18\x05 \x01(\x08\x12\x10\n\x08pin_code\x18\x06 \x01(\r\x12)\n\x05theme\x18\x07 \x01(\x0e\x32\x1a.meshtastic.protobuf.Theme\x12\x15\n\ralert_enabled\x18\x08 \x01(\x08\x12\x16\n\x0e\x62\x61nner_enabled\x18\t \x01(\x08\x12\x14\n\x0cring_tone_id\x18\n \x01(\r\x12/\n\x08language\x18\x0b \x01(\x0e\x32\x1d.meshtastic.protobuf.Language\x12\x34\n\x0bnode_filter\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.NodeFilter\x12:\n\x0enode_highlight\x18\r \x01(\x0b\x32\".meshtastic.protobuf.NodeHighlight\x12\x18\n\x10\x63\x61libration_data\x18\x0e \x01(\x0c\x12*\n\x08map_data\x18\x0f \x01(\x0b\x32\x18.meshtastic.protobuf.Map\"\xa7\x01\n\nNodeFilter\x12\x16\n\x0eunknown_switch\x18\x01 \x01(\x08\x12\x16\n\x0eoffline_switch\x18\x02 \x01(\x08\x12\x19\n\x11public_key_switch\x18\x03 \x01(\x08\x12\x11\n\thops_away\x18\x04 \x01(\x05\x12\x17\n\x0fposition_switch\x18\x05 \x01(\x08\x12\x11\n\tnode_name\x18\x06 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\x05\"~\n\rNodeHighlight\x12\x13\n\x0b\x63hat_switch\x18\x01 \x01(\x08\x12\x17\n\x0fposition_switch\x18\x02 \x01(\x08\x12\x18\n\x10telemetry_switch\x18\x03 \x01(\x08\x12\x12\n\niaq_switch\x18\x04 \x01(\x08\x12\x11\n\tnode_name\x18\x05 \x01(\t\"=\n\x08GeoPoint\x12\x0c\n\x04zoom\x18\x01 \x01(\x05\x12\x10\n\x08latitude\x18\x02 \x01(\x05\x12\x11\n\tlongitude\x18\x03 \x01(\x05\"U\n\x03Map\x12+\n\x04home\x18\x01 \x01(\x0b\x32\x1d.meshtastic.protobuf.GeoPoint\x12\r\n\x05style\x18\x02 \x01(\t\x12\x12\n\nfollow_gps\x18\x03 \x01(\x08*%\n\x05Theme\x12\x08\n\x04\x44\x41RK\x10\x00\x12\t\n\x05LIGHT\x10\x01\x12\x07\n\x03RED\x10\x02*\x8b\x02\n\x08Language\x12\x0b\n\x07\x45NGLISH\x10\x00\x12\n\n\x06\x46RENCH\x10\x01\x12\n\n\x06GERMAN\x10\x02\x12\x0b\n\x07ITALIAN\x10\x03\x12\x0e\n\nPORTUGUESE\x10\x04\x12\x0b\n\x07SPANISH\x10\x05\x12\x0b\n\x07SWEDISH\x10\x06\x12\x0b\n\x07\x46INNISH\x10\x07\x12\n\n\x06POLISH\x10\x08\x12\x0b\n\x07TURKISH\x10\t\x12\x0b\n\x07SERBIAN\x10\n\x12\x0b\n\x07RUSSIAN\x10\x0b\x12\t\n\x05\x44UTCH\x10\x0c\x12\t\n\x05GREEK\x10\r\x12\r\n\tNORWEGIAN\x10\x0e\x12\r\n\tSLOVENIAN\x10\x0f\x12\x16\n\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n\x13TRADITIONAL_CHINESE\x10\x1f\x42\x63\n\x13\x63om.geeksville.meshB\x0e\x44\x65viceUIProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.device_ui_pb2', _globals)
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016DeviceUIProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_globals['_THEME']._serialized_start=1002
|
||||
_globals['_THEME']._serialized_end=1039
|
||||
_globals['_LANGUAGE']._serialized_start=1042
|
||||
_globals['_LANGUAGE']._serialized_end=1309
|
||||
_globals['_DEVICEUICONFIG']._serialized_start=61
|
||||
_globals['_DEVICEUICONFIG']._serialized_end=552
|
||||
_globals['_NODEFILTER']._serialized_start=555
|
||||
_globals['_NODEFILTER']._serialized_end=722
|
||||
_globals['_NODEHIGHLIGHT']._serialized_start=724
|
||||
_globals['_NODEHIGHLIGHT']._serialized_end=850
|
||||
_globals['_GEOPOINT']._serialized_start=852
|
||||
_globals['_GEOPOINT']._serialized_end=913
|
||||
_globals['_MAP']._serialized_start=915
|
||||
_globals['_MAP']._serialized_end=1000
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
471
meshtastic/protobuf/device_ui_pb2.pyi
generated
Normal file
471
meshtastic/protobuf/device_ui_pb2.pyi
generated
Normal file
@@ -0,0 +1,471 @@
|
||||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
"""
|
||||
|
||||
import builtins
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.internal.enum_type_wrapper
|
||||
import google.protobuf.message
|
||||
import sys
|
||||
import typing
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
import typing as typing_extensions
|
||||
else:
|
||||
import typing_extensions
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
|
||||
class _Theme:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _ThemeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Theme.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
DARK: _Theme.ValueType # 0
|
||||
"""
|
||||
Dark
|
||||
"""
|
||||
LIGHT: _Theme.ValueType # 1
|
||||
"""
|
||||
Light
|
||||
"""
|
||||
RED: _Theme.ValueType # 2
|
||||
"""
|
||||
Red
|
||||
"""
|
||||
|
||||
class Theme(_Theme, metaclass=_ThemeEnumTypeWrapper): ...
|
||||
|
||||
DARK: Theme.ValueType # 0
|
||||
"""
|
||||
Dark
|
||||
"""
|
||||
LIGHT: Theme.ValueType # 1
|
||||
"""
|
||||
Light
|
||||
"""
|
||||
RED: Theme.ValueType # 2
|
||||
"""
|
||||
Red
|
||||
"""
|
||||
global___Theme = Theme
|
||||
|
||||
class _Language:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _LanguageEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Language.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
ENGLISH: _Language.ValueType # 0
|
||||
"""
|
||||
English
|
||||
"""
|
||||
FRENCH: _Language.ValueType # 1
|
||||
"""
|
||||
French
|
||||
"""
|
||||
GERMAN: _Language.ValueType # 2
|
||||
"""
|
||||
German
|
||||
"""
|
||||
ITALIAN: _Language.ValueType # 3
|
||||
"""
|
||||
Italian
|
||||
"""
|
||||
PORTUGUESE: _Language.ValueType # 4
|
||||
"""
|
||||
Portuguese
|
||||
"""
|
||||
SPANISH: _Language.ValueType # 5
|
||||
"""
|
||||
Spanish
|
||||
"""
|
||||
SWEDISH: _Language.ValueType # 6
|
||||
"""
|
||||
Swedish
|
||||
"""
|
||||
FINNISH: _Language.ValueType # 7
|
||||
"""
|
||||
Finnish
|
||||
"""
|
||||
POLISH: _Language.ValueType # 8
|
||||
"""
|
||||
Polish
|
||||
"""
|
||||
TURKISH: _Language.ValueType # 9
|
||||
"""
|
||||
Turkish
|
||||
"""
|
||||
SERBIAN: _Language.ValueType # 10
|
||||
"""
|
||||
Serbian
|
||||
"""
|
||||
RUSSIAN: _Language.ValueType # 11
|
||||
"""
|
||||
Russian
|
||||
"""
|
||||
DUTCH: _Language.ValueType # 12
|
||||
"""
|
||||
Dutch
|
||||
"""
|
||||
GREEK: _Language.ValueType # 13
|
||||
"""
|
||||
Greek
|
||||
"""
|
||||
NORWEGIAN: _Language.ValueType # 14
|
||||
"""
|
||||
Norwegian
|
||||
"""
|
||||
SLOVENIAN: _Language.ValueType # 15
|
||||
"""
|
||||
Slovenian
|
||||
"""
|
||||
SIMPLIFIED_CHINESE: _Language.ValueType # 30
|
||||
"""
|
||||
Simplified Chinese (experimental)
|
||||
"""
|
||||
TRADITIONAL_CHINESE: _Language.ValueType # 31
|
||||
"""
|
||||
Traditional Chinese (experimental)
|
||||
"""
|
||||
|
||||
class Language(_Language, metaclass=_LanguageEnumTypeWrapper):
|
||||
"""
|
||||
Localization
|
||||
"""
|
||||
|
||||
ENGLISH: Language.ValueType # 0
|
||||
"""
|
||||
English
|
||||
"""
|
||||
FRENCH: Language.ValueType # 1
|
||||
"""
|
||||
French
|
||||
"""
|
||||
GERMAN: Language.ValueType # 2
|
||||
"""
|
||||
German
|
||||
"""
|
||||
ITALIAN: Language.ValueType # 3
|
||||
"""
|
||||
Italian
|
||||
"""
|
||||
PORTUGUESE: Language.ValueType # 4
|
||||
"""
|
||||
Portuguese
|
||||
"""
|
||||
SPANISH: Language.ValueType # 5
|
||||
"""
|
||||
Spanish
|
||||
"""
|
||||
SWEDISH: Language.ValueType # 6
|
||||
"""
|
||||
Swedish
|
||||
"""
|
||||
FINNISH: Language.ValueType # 7
|
||||
"""
|
||||
Finnish
|
||||
"""
|
||||
POLISH: Language.ValueType # 8
|
||||
"""
|
||||
Polish
|
||||
"""
|
||||
TURKISH: Language.ValueType # 9
|
||||
"""
|
||||
Turkish
|
||||
"""
|
||||
SERBIAN: Language.ValueType # 10
|
||||
"""
|
||||
Serbian
|
||||
"""
|
||||
RUSSIAN: Language.ValueType # 11
|
||||
"""
|
||||
Russian
|
||||
"""
|
||||
DUTCH: Language.ValueType # 12
|
||||
"""
|
||||
Dutch
|
||||
"""
|
||||
GREEK: Language.ValueType # 13
|
||||
"""
|
||||
Greek
|
||||
"""
|
||||
NORWEGIAN: Language.ValueType # 14
|
||||
"""
|
||||
Norwegian
|
||||
"""
|
||||
SLOVENIAN: Language.ValueType # 15
|
||||
"""
|
||||
Slovenian
|
||||
"""
|
||||
SIMPLIFIED_CHINESE: Language.ValueType # 30
|
||||
"""
|
||||
Simplified Chinese (experimental)
|
||||
"""
|
||||
TRADITIONAL_CHINESE: Language.ValueType # 31
|
||||
"""
|
||||
Traditional Chinese (experimental)
|
||||
"""
|
||||
global___Language = Language
|
||||
|
||||
@typing.final
|
||||
class DeviceUIConfig(google.protobuf.message.Message):
|
||||
"""
|
||||
Protobuf structures for device-ui persistency
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
VERSION_FIELD_NUMBER: builtins.int
|
||||
SCREEN_BRIGHTNESS_FIELD_NUMBER: builtins.int
|
||||
SCREEN_TIMEOUT_FIELD_NUMBER: builtins.int
|
||||
SCREEN_LOCK_FIELD_NUMBER: builtins.int
|
||||
SETTINGS_LOCK_FIELD_NUMBER: builtins.int
|
||||
PIN_CODE_FIELD_NUMBER: builtins.int
|
||||
THEME_FIELD_NUMBER: builtins.int
|
||||
ALERT_ENABLED_FIELD_NUMBER: builtins.int
|
||||
BANNER_ENABLED_FIELD_NUMBER: builtins.int
|
||||
RING_TONE_ID_FIELD_NUMBER: builtins.int
|
||||
LANGUAGE_FIELD_NUMBER: builtins.int
|
||||
NODE_FILTER_FIELD_NUMBER: builtins.int
|
||||
NODE_HIGHLIGHT_FIELD_NUMBER: builtins.int
|
||||
CALIBRATION_DATA_FIELD_NUMBER: builtins.int
|
||||
MAP_DATA_FIELD_NUMBER: builtins.int
|
||||
version: builtins.int
|
||||
"""
|
||||
A version integer used to invalidate saved files when we make incompatible changes.
|
||||
"""
|
||||
screen_brightness: builtins.int
|
||||
"""
|
||||
TFT display brightness 1..255
|
||||
"""
|
||||
screen_timeout: builtins.int
|
||||
"""
|
||||
Screen timeout 0..900
|
||||
"""
|
||||
screen_lock: builtins.bool
|
||||
"""
|
||||
Screen/Settings lock enabled
|
||||
"""
|
||||
settings_lock: builtins.bool
|
||||
pin_code: builtins.int
|
||||
theme: global___Theme.ValueType
|
||||
"""
|
||||
Color theme
|
||||
"""
|
||||
alert_enabled: builtins.bool
|
||||
"""
|
||||
Audible message, banner and ring tone
|
||||
"""
|
||||
banner_enabled: builtins.bool
|
||||
ring_tone_id: builtins.int
|
||||
language: global___Language.ValueType
|
||||
"""
|
||||
Localization
|
||||
"""
|
||||
calibration_data: builtins.bytes
|
||||
"""
|
||||
8 integers for screen calibration data
|
||||
"""
|
||||
@property
|
||||
def node_filter(self) -> global___NodeFilter:
|
||||
"""
|
||||
Node list filter
|
||||
"""
|
||||
|
||||
@property
|
||||
def node_highlight(self) -> global___NodeHighlight:
|
||||
"""
|
||||
Node list highlightening
|
||||
"""
|
||||
|
||||
@property
|
||||
def map_data(self) -> global___Map:
|
||||
"""
|
||||
Map related data
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
version: builtins.int = ...,
|
||||
screen_brightness: builtins.int = ...,
|
||||
screen_timeout: builtins.int = ...,
|
||||
screen_lock: builtins.bool = ...,
|
||||
settings_lock: builtins.bool = ...,
|
||||
pin_code: builtins.int = ...,
|
||||
theme: global___Theme.ValueType = ...,
|
||||
alert_enabled: builtins.bool = ...,
|
||||
banner_enabled: builtins.bool = ...,
|
||||
ring_tone_id: builtins.int = ...,
|
||||
language: global___Language.ValueType = ...,
|
||||
node_filter: global___NodeFilter | None = ...,
|
||||
node_highlight: global___NodeHighlight | None = ...,
|
||||
calibration_data: builtins.bytes = ...,
|
||||
map_data: global___Map | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["alert_enabled", b"alert_enabled", "banner_enabled", b"banner_enabled", "calibration_data", b"calibration_data", "language", b"language", "map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight", "pin_code", b"pin_code", "ring_tone_id", b"ring_tone_id", "screen_brightness", b"screen_brightness", "screen_lock", b"screen_lock", "screen_timeout", b"screen_timeout", "settings_lock", b"settings_lock", "theme", b"theme", "version", b"version"]) -> None: ...
|
||||
|
||||
global___DeviceUIConfig = DeviceUIConfig
|
||||
|
||||
@typing.final
|
||||
class NodeFilter(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
UNKNOWN_SWITCH_FIELD_NUMBER: builtins.int
|
||||
OFFLINE_SWITCH_FIELD_NUMBER: builtins.int
|
||||
PUBLIC_KEY_SWITCH_FIELD_NUMBER: builtins.int
|
||||
HOPS_AWAY_FIELD_NUMBER: builtins.int
|
||||
POSITION_SWITCH_FIELD_NUMBER: builtins.int
|
||||
NODE_NAME_FIELD_NUMBER: builtins.int
|
||||
CHANNEL_FIELD_NUMBER: builtins.int
|
||||
unknown_switch: builtins.bool
|
||||
"""
|
||||
Filter unknown nodes
|
||||
"""
|
||||
offline_switch: builtins.bool
|
||||
"""
|
||||
Filter offline nodes
|
||||
"""
|
||||
public_key_switch: builtins.bool
|
||||
"""
|
||||
Filter nodes w/o public key
|
||||
"""
|
||||
hops_away: builtins.int
|
||||
"""
|
||||
Filter based on hops away
|
||||
"""
|
||||
position_switch: builtins.bool
|
||||
"""
|
||||
Filter nodes w/o position
|
||||
"""
|
||||
node_name: builtins.str
|
||||
"""
|
||||
Filter nodes by matching name string
|
||||
"""
|
||||
channel: builtins.int
|
||||
"""
|
||||
Filter based on channel
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
unknown_switch: builtins.bool = ...,
|
||||
offline_switch: builtins.bool = ...,
|
||||
public_key_switch: builtins.bool = ...,
|
||||
hops_away: builtins.int = ...,
|
||||
position_switch: builtins.bool = ...,
|
||||
node_name: builtins.str = ...,
|
||||
channel: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "hops_away", b"hops_away", "node_name", b"node_name", "offline_switch", b"offline_switch", "position_switch", b"position_switch", "public_key_switch", b"public_key_switch", "unknown_switch", b"unknown_switch"]) -> None: ...
|
||||
|
||||
global___NodeFilter = NodeFilter
|
||||
|
||||
@typing.final
|
||||
class NodeHighlight(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
CHAT_SWITCH_FIELD_NUMBER: builtins.int
|
||||
POSITION_SWITCH_FIELD_NUMBER: builtins.int
|
||||
TELEMETRY_SWITCH_FIELD_NUMBER: builtins.int
|
||||
IAQ_SWITCH_FIELD_NUMBER: builtins.int
|
||||
NODE_NAME_FIELD_NUMBER: builtins.int
|
||||
chat_switch: builtins.bool
|
||||
"""
|
||||
Hightlight nodes w/ active chat
|
||||
"""
|
||||
position_switch: builtins.bool
|
||||
"""
|
||||
Highlight nodes w/ position
|
||||
"""
|
||||
telemetry_switch: builtins.bool
|
||||
"""
|
||||
Highlight nodes w/ telemetry data
|
||||
"""
|
||||
iaq_switch: builtins.bool
|
||||
"""
|
||||
Highlight nodes w/ iaq data
|
||||
"""
|
||||
node_name: builtins.str
|
||||
"""
|
||||
Highlight nodes by matching name string
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
chat_switch: builtins.bool = ...,
|
||||
position_switch: builtins.bool = ...,
|
||||
telemetry_switch: builtins.bool = ...,
|
||||
iaq_switch: builtins.bool = ...,
|
||||
node_name: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["chat_switch", b"chat_switch", "iaq_switch", b"iaq_switch", "node_name", b"node_name", "position_switch", b"position_switch", "telemetry_switch", b"telemetry_switch"]) -> None: ...
|
||||
|
||||
global___NodeHighlight = NodeHighlight
|
||||
|
||||
@typing.final
|
||||
class GeoPoint(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
ZOOM_FIELD_NUMBER: builtins.int
|
||||
LATITUDE_FIELD_NUMBER: builtins.int
|
||||
LONGITUDE_FIELD_NUMBER: builtins.int
|
||||
zoom: builtins.int
|
||||
"""
|
||||
Zoom level
|
||||
"""
|
||||
latitude: builtins.int
|
||||
"""
|
||||
Coordinate: latitude
|
||||
"""
|
||||
longitude: builtins.int
|
||||
"""
|
||||
Coordinate: longitude
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
zoom: builtins.int = ...,
|
||||
latitude: builtins.int = ...,
|
||||
longitude: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["latitude", b"latitude", "longitude", b"longitude", "zoom", b"zoom"]) -> None: ...
|
||||
|
||||
global___GeoPoint = GeoPoint
|
||||
|
||||
@typing.final
|
||||
class Map(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
HOME_FIELD_NUMBER: builtins.int
|
||||
STYLE_FIELD_NUMBER: builtins.int
|
||||
FOLLOW_GPS_FIELD_NUMBER: builtins.int
|
||||
style: builtins.str
|
||||
"""
|
||||
Map tile style
|
||||
"""
|
||||
follow_gps: builtins.bool
|
||||
"""
|
||||
Map scroll follows GPS
|
||||
"""
|
||||
@property
|
||||
def home(self) -> global___GeoPoint:
|
||||
"""
|
||||
Home coordinates
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
home: global___GeoPoint | None = ...,
|
||||
style: builtins.str = ...,
|
||||
follow_gps: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["home", b"home"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["follow_gps", b"follow_gps", "home", b"home", "style", b"style"]) -> None: ...
|
||||
|
||||
global___Map = Map
|
||||
39
meshtastic/protobuf/deviceonly_pb2.py
generated
39
meshtastic/protobuf/deviceonly_pb2.py
generated
@@ -12,13 +12,14 @@ _sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from meshtastic.protobuf import channel_pb2 as meshtastic_dot_protobuf_dot_channel__pb2
|
||||
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
|
||||
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
|
||||
from meshtastic.protobuf import telemetry_pb2 as meshtastic_dot_protobuf_dot_telemetry__pb2
|
||||
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
|
||||
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
|
||||
import nanopb_pb2 as nanopb__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/deviceonly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a\x0cnanopb.proto\"\x99\x01\n\x0cPositionLite\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\x0c\n\x04time\x18\x04 \x01(\x07\x12@\n\x0flocation_source\x18\x05 \x01(\x0e\x32\'.meshtastic.protobuf.Position.LocSource\"\xa1\x02\n\x0cNodeInfoLite\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\'\n\x04user\x18\x02 \x01(\x0b\x32\x19.meshtastic.protobuf.User\x12\x33\n\x08position\x18\x03 \x01(\x0b\x32!.meshtastic.protobuf.PositionLite\x12\x0b\n\x03snr\x18\x04 \x01(\x02\x12\x12\n\nlast_heard\x18\x05 \x01(\x07\x12:\n\x0e\x64\x65vice_metrics\x18\x06 \x01(\x0b\x32\".meshtastic.protobuf.DeviceMetrics\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\r\x12\x10\n\x08via_mqtt\x18\x08 \x01(\x08\x12\x11\n\thops_away\x18\t \x01(\r\x12\x13\n\x0bis_favorite\x18\n \x01(\x08\"\x82\x04\n\x0b\x44\x65viceState\x12\x30\n\x07my_node\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.MyNodeInfo\x12(\n\x05owner\x18\x03 \x01(\x0b\x32\x19.meshtastic.protobuf.User\x12\x36\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12\x38\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x13\n\x07no_save\x18\t \x01(\x08\x42\x02\x18\x01\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08\x12\x34\n\x0brx_waypoint\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12M\n\x19node_remote_hardware_pins\x18\r \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePin\x12\x63\n\x0cnode_db_lite\x18\x0e \x03(\x0b\x32!.meshtastic.protobuf.NodeInfoLiteB*\x92?\'\x92\x01$std::vector<meshtastic_NodeInfoLite>\"N\n\x0b\x43hannelFile\x12.\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1c.meshtastic.protobuf.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\xb2\x02\n\x08OEMStore\x12\x16\n\x0eoem_icon_width\x18\x01 \x01(\r\x12\x17\n\x0foem_icon_height\x18\x02 \x01(\r\x12\x15\n\roem_icon_bits\x18\x03 \x01(\x0c\x12\x32\n\x08oem_font\x18\x04 \x01(\x0e\x32 .meshtastic.protobuf.ScreenFonts\x12\x10\n\x08oem_text\x18\x05 \x01(\t\x12\x13\n\x0boem_aes_key\x18\x06 \x01(\x0c\x12:\n\x10oem_local_config\x18\x07 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfig\x12G\n\x17oem_local_module_config\x18\x08 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfig*>\n\x0bScreenFonts\x12\x0e\n\nFONT_SMALL\x10\x00\x12\x0f\n\x0b\x46ONT_MEDIUM\x10\x01\x12\x0e\n\nFONT_LARGE\x10\x02\x42m\n\x13\x63om.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x92?\x0b\xc2\x01\x08<vector>b\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/deviceonly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/config.proto\x1a#meshtastic/protobuf/localonly.proto\x1a\x0cnanopb.proto\"\x99\x01\n\x0cPositionLite\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\x0c\n\x04time\x18\x04 \x01(\x07\x12@\n\x0flocation_source\x18\x05 \x01(\x0e\x32\'.meshtastic.protobuf.Position.LocSource\"\xe2\x01\n\x08UserLite\x12\x13\n\x07macaddr\x18\x01 \x01(\x0c\x42\x02\x18\x01\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x34\n\x08hw_model\x18\x04 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x13\n\x0bis_licensed\x18\x05 \x01(\x08\x12;\n\x04role\x18\x06 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x12\n\npublic_key\x18\x07 \x01(\x0c\"\xde\x02\n\x0cNodeInfoLite\x12\x0b\n\x03num\x18\x01 \x01(\r\x12+\n\x04user\x18\x02 \x01(\x0b\x32\x1d.meshtastic.protobuf.UserLite\x12\x33\n\x08position\x18\x03 \x01(\x0b\x32!.meshtastic.protobuf.PositionLite\x12\x0b\n\x03snr\x18\x04 \x01(\x02\x12\x12\n\nlast_heard\x18\x05 \x01(\x07\x12:\n\x0e\x64\x65vice_metrics\x18\x06 \x01(\x0b\x32\".meshtastic.protobuf.DeviceMetrics\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\r\x12\x10\n\x08via_mqtt\x18\x08 \x01(\x08\x12\x16\n\thops_away\x18\t \x01(\rH\x00\x88\x01\x01\x12\x13\n\x0bis_favorite\x18\n \x01(\x08\x12\x12\n\nis_ignored\x18\x0b \x01(\x08\x12\x10\n\x08next_hop\x18\x0c \x01(\rB\x0c\n\n_hops_away\"\xa1\x03\n\x0b\x44\x65viceState\x12\x30\n\x07my_node\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.MyNodeInfo\x12(\n\x05owner\x18\x03 \x01(\x0b\x32\x19.meshtastic.protobuf.User\x12\x36\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12\x38\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x13\n\x07no_save\x18\t \x01(\x08\x42\x02\x18\x01\x12\x19\n\rdid_gps_reset\x18\x0b \x01(\x08\x42\x02\x18\x01\x12\x34\n\x0brx_waypoint\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12M\n\x19node_remote_hardware_pins\x18\r \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePin\"}\n\x0cNodeDatabase\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\\\n\x05nodes\x18\x02 \x03(\x0b\x32!.meshtastic.protobuf.NodeInfoLiteB*\x92?\'\x92\x01$std::vector<meshtastic_NodeInfoLite>\"N\n\x0b\x43hannelFile\x12.\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1c.meshtastic.protobuf.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x86\x02\n\x11\x42\x61\x63kupPreferences\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\x07\x12\x30\n\x06\x63onfig\x18\x03 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfig\x12=\n\rmodule_config\x18\x04 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfig\x12\x32\n\x08\x63hannels\x18\x05 \x01(\x0b\x32 .meshtastic.protobuf.ChannelFile\x12(\n\x05owner\x18\x06 \x01(\x0b\x32\x19.meshtastic.protobuf.UserBm\n\x13\x63om.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x92?\x0b\xc2\x01\x08<vector>b\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
@@ -26,20 +27,26 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.deviceo
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000\222?\013\302\001\010<vector>'
|
||||
_USERLITE.fields_by_name['macaddr']._options = None
|
||||
_USERLITE.fields_by_name['macaddr']._serialized_options = b'\030\001'
|
||||
_DEVICESTATE.fields_by_name['no_save']._options = None
|
||||
_DEVICESTATE.fields_by_name['no_save']._serialized_options = b'\030\001'
|
||||
_DEVICESTATE.fields_by_name['node_db_lite']._options = None
|
||||
_DEVICESTATE.fields_by_name['node_db_lite']._serialized_options = b'\222?\'\222\001$std::vector<meshtastic_NodeInfoLite>'
|
||||
_globals['_SCREENFONTS']._serialized_start=1570
|
||||
_globals['_SCREENFONTS']._serialized_end=1632
|
||||
_globals['_POSITIONLITE']._serialized_start=217
|
||||
_globals['_POSITIONLITE']._serialized_end=370
|
||||
_globals['_NODEINFOLITE']._serialized_start=373
|
||||
_globals['_NODEINFOLITE']._serialized_end=662
|
||||
_globals['_DEVICESTATE']._serialized_start=665
|
||||
_globals['_DEVICESTATE']._serialized_end=1179
|
||||
_globals['_CHANNELFILE']._serialized_start=1181
|
||||
_globals['_CHANNELFILE']._serialized_end=1259
|
||||
_globals['_OEMSTORE']._serialized_start=1262
|
||||
_globals['_OEMSTORE']._serialized_end=1568
|
||||
_DEVICESTATE.fields_by_name['did_gps_reset']._options = None
|
||||
_DEVICESTATE.fields_by_name['did_gps_reset']._serialized_options = b'\030\001'
|
||||
_NODEDATABASE.fields_by_name['nodes']._options = None
|
||||
_NODEDATABASE.fields_by_name['nodes']._serialized_options = b'\222?\'\222\001$std::vector<meshtastic_NodeInfoLite>'
|
||||
_globals['_POSITIONLITE']._serialized_start=251
|
||||
_globals['_POSITIONLITE']._serialized_end=404
|
||||
_globals['_USERLITE']._serialized_start=407
|
||||
_globals['_USERLITE']._serialized_end=633
|
||||
_globals['_NODEINFOLITE']._serialized_start=636
|
||||
_globals['_NODEINFOLITE']._serialized_end=986
|
||||
_globals['_DEVICESTATE']._serialized_start=989
|
||||
_globals['_DEVICESTATE']._serialized_end=1406
|
||||
_globals['_NODEDATABASE']._serialized_start=1408
|
||||
_globals['_NODEDATABASE']._serialized_end=1533
|
||||
_globals['_CHANNELFILE']._serialized_start=1535
|
||||
_globals['_CHANNELFILE']._serialized_end=1613
|
||||
_globals['_BACKUPPREFERENCES']._serialized_start=1616
|
||||
_globals['_BACKUPPREFERENCES']._serialized_end=1878
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
||||
257
meshtastic/protobuf/deviceonly_pb2.pyi
generated
257
meshtastic/protobuf/deviceonly_pb2.pyi
generated
@@ -7,60 +7,16 @@ import builtins
|
||||
import collections.abc
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.internal.containers
|
||||
import google.protobuf.internal.enum_type_wrapper
|
||||
import google.protobuf.message
|
||||
import meshtastic.protobuf.channel_pb2
|
||||
import meshtastic.protobuf.config_pb2
|
||||
import meshtastic.protobuf.localonly_pb2
|
||||
import meshtastic.protobuf.mesh_pb2
|
||||
import meshtastic.protobuf.telemetry_pb2
|
||||
import sys
|
||||
import typing
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
import typing as typing_extensions
|
||||
else:
|
||||
import typing_extensions
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
|
||||
class _ScreenFonts:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _ScreenFontsEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_ScreenFonts.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
FONT_SMALL: _ScreenFonts.ValueType # 0
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
FONT_MEDIUM: _ScreenFonts.ValueType # 1
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
FONT_LARGE: _ScreenFonts.ValueType # 2
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
|
||||
class ScreenFonts(_ScreenFonts, metaclass=_ScreenFontsEnumTypeWrapper):
|
||||
"""
|
||||
Font sizes for the device screen
|
||||
"""
|
||||
|
||||
FONT_SMALL: ScreenFonts.ValueType # 0
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
FONT_MEDIUM: ScreenFonts.ValueType # 1
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
FONT_LARGE: ScreenFonts.ValueType # 2
|
||||
"""
|
||||
TODO: REPLACE
|
||||
"""
|
||||
global___ScreenFonts = ScreenFonts
|
||||
|
||||
@typing.final
|
||||
class PositionLite(google.protobuf.message.Message):
|
||||
"""
|
||||
@@ -112,6 +68,67 @@ class PositionLite(google.protobuf.message.Message):
|
||||
|
||||
global___PositionLite = PositionLite
|
||||
|
||||
@typing.final
|
||||
class UserLite(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
MACADDR_FIELD_NUMBER: builtins.int
|
||||
LONG_NAME_FIELD_NUMBER: builtins.int
|
||||
SHORT_NAME_FIELD_NUMBER: builtins.int
|
||||
HW_MODEL_FIELD_NUMBER: builtins.int
|
||||
IS_LICENSED_FIELD_NUMBER: builtins.int
|
||||
ROLE_FIELD_NUMBER: builtins.int
|
||||
PUBLIC_KEY_FIELD_NUMBER: builtins.int
|
||||
macaddr: builtins.bytes
|
||||
"""
|
||||
This is the addr of the radio.
|
||||
"""
|
||||
long_name: builtins.str
|
||||
"""
|
||||
A full name for this user, i.e. "Kevin Hester"
|
||||
"""
|
||||
short_name: builtins.str
|
||||
"""
|
||||
A VERY short name, ideally two characters.
|
||||
Suitable for a tiny OLED screen
|
||||
"""
|
||||
hw_model: meshtastic.protobuf.mesh_pb2.HardwareModel.ValueType
|
||||
"""
|
||||
TBEAM, HELTEC, etc...
|
||||
Starting in 1.2.11 moved to hw_model enum in the NodeInfo object.
|
||||
Apps will still need the string here for older builds
|
||||
(so OTA update can find the right image), but if the enum is available it will be used instead.
|
||||
"""
|
||||
is_licensed: builtins.bool
|
||||
"""
|
||||
In some regions Ham radio operators have different bandwidth limitations than others.
|
||||
If this user is a licensed operator, set this flag.
|
||||
Also, "long_name" should be their licence number.
|
||||
"""
|
||||
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType
|
||||
"""
|
||||
Indicates that the user's role in the mesh
|
||||
"""
|
||||
public_key: builtins.bytes
|
||||
"""
|
||||
The public key of the user's device.
|
||||
This is sent out to other nodes on the mesh to allow them to compute a shared secret key.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
macaddr: builtins.bytes = ...,
|
||||
long_name: builtins.str = ...,
|
||||
short_name: builtins.str = ...,
|
||||
hw_model: meshtastic.protobuf.mesh_pb2.HardwareModel.ValueType = ...,
|
||||
is_licensed: builtins.bool = ...,
|
||||
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
|
||||
public_key: builtins.bytes = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["hw_model", b"hw_model", "is_licensed", b"is_licensed", "long_name", b"long_name", "macaddr", b"macaddr", "public_key", b"public_key", "role", b"role", "short_name", b"short_name"]) -> None: ...
|
||||
|
||||
global___UserLite = UserLite
|
||||
|
||||
@typing.final
|
||||
class NodeInfoLite(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
@@ -126,6 +143,8 @@ class NodeInfoLite(google.protobuf.message.Message):
|
||||
VIA_MQTT_FIELD_NUMBER: builtins.int
|
||||
HOPS_AWAY_FIELD_NUMBER: builtins.int
|
||||
IS_FAVORITE_FIELD_NUMBER: builtins.int
|
||||
IS_IGNORED_FIELD_NUMBER: builtins.int
|
||||
NEXT_HOP_FIELD_NUMBER: builtins.int
|
||||
num: builtins.int
|
||||
"""
|
||||
The node number
|
||||
@@ -149,15 +168,24 @@ class NodeInfoLite(google.protobuf.message.Message):
|
||||
"""
|
||||
hops_away: builtins.int
|
||||
"""
|
||||
Number of hops away from us this node is (0 if adjacent)
|
||||
Number of hops away from us this node is (0 if direct neighbor)
|
||||
"""
|
||||
is_favorite: builtins.bool
|
||||
"""
|
||||
True if node is in our favorites list
|
||||
Persists between NodeDB internal clean ups
|
||||
"""
|
||||
is_ignored: builtins.bool
|
||||
"""
|
||||
True if node is in our ignored list
|
||||
Persists between NodeDB internal clean ups
|
||||
"""
|
||||
next_hop: builtins.int
|
||||
"""
|
||||
Last byte of the node number of the node that should be used as the next hop to reach this node.
|
||||
"""
|
||||
@property
|
||||
def user(self) -> meshtastic.protobuf.mesh_pb2.User:
|
||||
def user(self) -> global___UserLite:
|
||||
"""
|
||||
The user info for this node
|
||||
"""
|
||||
@@ -179,18 +207,21 @@ class NodeInfoLite(google.protobuf.message.Message):
|
||||
self,
|
||||
*,
|
||||
num: builtins.int = ...,
|
||||
user: meshtastic.protobuf.mesh_pb2.User | None = ...,
|
||||
user: global___UserLite | None = ...,
|
||||
position: global___PositionLite | None = ...,
|
||||
snr: builtins.float = ...,
|
||||
last_heard: builtins.int = ...,
|
||||
device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ...,
|
||||
channel: builtins.int = ...,
|
||||
via_mqtt: builtins.bool = ...,
|
||||
hops_away: builtins.int = ...,
|
||||
hops_away: builtins.int | None = ...,
|
||||
is_favorite: builtins.bool = ...,
|
||||
is_ignored: builtins.bool = ...,
|
||||
next_hop: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["device_metrics", b"device_metrics", "position", b"position", "user", b"user"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "last_heard", b"last_heard", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "position", b"position", "user", b"user"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "last_heard", b"last_heard", "next_hop", b"next_hop", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_hops_away", b"_hops_away"]) -> typing.Literal["hops_away"] | None: ...
|
||||
|
||||
global___NodeInfoLite = NodeInfoLite
|
||||
|
||||
@@ -215,7 +246,6 @@ class DeviceState(google.protobuf.message.Message):
|
||||
DID_GPS_RESET_FIELD_NUMBER: builtins.int
|
||||
RX_WAYPOINT_FIELD_NUMBER: builtins.int
|
||||
NODE_REMOTE_HARDWARE_PINS_FIELD_NUMBER: builtins.int
|
||||
NODE_DB_LITE_FIELD_NUMBER: builtins.int
|
||||
version: builtins.int
|
||||
"""
|
||||
A version integer used to invalidate old save files when we make
|
||||
@@ -230,7 +260,8 @@ class DeviceState(google.protobuf.message.Message):
|
||||
"""
|
||||
did_gps_reset: builtins.bool
|
||||
"""
|
||||
Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset.
|
||||
Previously used to manage GPS factory resets.
|
||||
Deprecated in 2.5.23
|
||||
"""
|
||||
@property
|
||||
def my_node(self) -> meshtastic.protobuf.mesh_pb2.MyNodeInfo:
|
||||
@@ -272,12 +303,6 @@ class DeviceState(google.protobuf.message.Message):
|
||||
The mesh's nodes with their available gpio pins for RemoteHardware module
|
||||
"""
|
||||
|
||||
@property
|
||||
def node_db_lite(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___NodeInfoLite]:
|
||||
"""
|
||||
New lite version of NodeDB to decrease memory footprint
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -290,13 +315,40 @@ class DeviceState(google.protobuf.message.Message):
|
||||
did_gps_reset: builtins.bool = ...,
|
||||
rx_waypoint: meshtastic.protobuf.mesh_pb2.MeshPacket | None = ...,
|
||||
node_remote_hardware_pins: collections.abc.Iterable[meshtastic.protobuf.mesh_pb2.NodeRemoteHardwarePin] | None = ...,
|
||||
node_db_lite: collections.abc.Iterable[global___NodeInfoLite] | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["my_node", b"my_node", "owner", b"owner", "rx_text_message", b"rx_text_message", "rx_waypoint", b"rx_waypoint"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["did_gps_reset", b"did_gps_reset", "my_node", b"my_node", "no_save", b"no_save", "node_db_lite", b"node_db_lite", "node_remote_hardware_pins", b"node_remote_hardware_pins", "owner", b"owner", "receive_queue", b"receive_queue", "rx_text_message", b"rx_text_message", "rx_waypoint", b"rx_waypoint", "version", b"version"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["did_gps_reset", b"did_gps_reset", "my_node", b"my_node", "no_save", b"no_save", "node_remote_hardware_pins", b"node_remote_hardware_pins", "owner", b"owner", "receive_queue", b"receive_queue", "rx_text_message", b"rx_text_message", "rx_waypoint", b"rx_waypoint", "version", b"version"]) -> None: ...
|
||||
|
||||
global___DeviceState = DeviceState
|
||||
|
||||
@typing.final
|
||||
class NodeDatabase(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
VERSION_FIELD_NUMBER: builtins.int
|
||||
NODES_FIELD_NUMBER: builtins.int
|
||||
version: builtins.int
|
||||
"""
|
||||
A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code.
|
||||
"""
|
||||
@property
|
||||
def nodes(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___NodeInfoLite]:
|
||||
"""
|
||||
New lite version of NodeDB to decrease memory footprint
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
version: builtins.int = ...,
|
||||
nodes: collections.abc.Iterable[global___NodeInfoLite] | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["nodes", b"nodes", "version", b"version"]) -> None: ...
|
||||
|
||||
global___NodeDatabase = NodeDatabase
|
||||
|
||||
@typing.final
|
||||
class ChannelFile(google.protobuf.message.Message):
|
||||
"""
|
||||
@@ -330,71 +382,62 @@ class ChannelFile(google.protobuf.message.Message):
|
||||
global___ChannelFile = ChannelFile
|
||||
|
||||
@typing.final
|
||||
class OEMStore(google.protobuf.message.Message):
|
||||
class BackupPreferences(google.protobuf.message.Message):
|
||||
"""
|
||||
This can be used for customizing the firmware distribution. If populated,
|
||||
show a secondary bootup screen with custom logo and text for 2.5 seconds.
|
||||
The on-disk backup of the node's preferences
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
OEM_ICON_WIDTH_FIELD_NUMBER: builtins.int
|
||||
OEM_ICON_HEIGHT_FIELD_NUMBER: builtins.int
|
||||
OEM_ICON_BITS_FIELD_NUMBER: builtins.int
|
||||
OEM_FONT_FIELD_NUMBER: builtins.int
|
||||
OEM_TEXT_FIELD_NUMBER: builtins.int
|
||||
OEM_AES_KEY_FIELD_NUMBER: builtins.int
|
||||
OEM_LOCAL_CONFIG_FIELD_NUMBER: builtins.int
|
||||
OEM_LOCAL_MODULE_CONFIG_FIELD_NUMBER: builtins.int
|
||||
oem_icon_width: builtins.int
|
||||
VERSION_FIELD_NUMBER: builtins.int
|
||||
TIMESTAMP_FIELD_NUMBER: builtins.int
|
||||
CONFIG_FIELD_NUMBER: builtins.int
|
||||
MODULE_CONFIG_FIELD_NUMBER: builtins.int
|
||||
CHANNELS_FIELD_NUMBER: builtins.int
|
||||
OWNER_FIELD_NUMBER: builtins.int
|
||||
version: builtins.int
|
||||
"""
|
||||
The Logo width in Px
|
||||
The version of the backup
|
||||
"""
|
||||
oem_icon_height: builtins.int
|
||||
timestamp: builtins.int
|
||||
"""
|
||||
The Logo height in Px
|
||||
"""
|
||||
oem_icon_bits: builtins.bytes
|
||||
"""
|
||||
The Logo in XBM bytechar format
|
||||
"""
|
||||
oem_font: global___ScreenFonts.ValueType
|
||||
"""
|
||||
Use this font for the OEM text.
|
||||
"""
|
||||
oem_text: builtins.str
|
||||
"""
|
||||
Use this font for the OEM text.
|
||||
"""
|
||||
oem_aes_key: builtins.bytes
|
||||
"""
|
||||
The default device encryption key, 16 or 32 byte
|
||||
The timestamp of the backup (if node has time)
|
||||
"""
|
||||
@property
|
||||
def oem_local_config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig:
|
||||
def config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig:
|
||||
"""
|
||||
A Preset LocalConfig to apply during factory reset
|
||||
The node's configuration
|
||||
"""
|
||||
|
||||
@property
|
||||
def oem_local_module_config(self) -> meshtastic.protobuf.localonly_pb2.LocalModuleConfig:
|
||||
def module_config(self) -> meshtastic.protobuf.localonly_pb2.LocalModuleConfig:
|
||||
"""
|
||||
A Preset LocalModuleConfig to apply during factory reset
|
||||
The node's module configuration
|
||||
"""
|
||||
|
||||
@property
|
||||
def channels(self) -> global___ChannelFile:
|
||||
"""
|
||||
The node's channels
|
||||
"""
|
||||
|
||||
@property
|
||||
def owner(self) -> meshtastic.protobuf.mesh_pb2.User:
|
||||
"""
|
||||
The node's user (owner) information
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
oem_icon_width: builtins.int = ...,
|
||||
oem_icon_height: builtins.int = ...,
|
||||
oem_icon_bits: builtins.bytes = ...,
|
||||
oem_font: global___ScreenFonts.ValueType = ...,
|
||||
oem_text: builtins.str = ...,
|
||||
oem_aes_key: builtins.bytes = ...,
|
||||
oem_local_config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ...,
|
||||
oem_local_module_config: meshtastic.protobuf.localonly_pb2.LocalModuleConfig | None = ...,
|
||||
version: builtins.int = ...,
|
||||
timestamp: builtins.int = ...,
|
||||
config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ...,
|
||||
module_config: meshtastic.protobuf.localonly_pb2.LocalModuleConfig | None = ...,
|
||||
channels: global___ChannelFile | None = ...,
|
||||
owner: meshtastic.protobuf.mesh_pb2.User | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["oem_local_config", b"oem_local_config", "oem_local_module_config", b"oem_local_module_config"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["oem_aes_key", b"oem_aes_key", "oem_font", b"oem_font", "oem_icon_bits", b"oem_icon_bits", "oem_icon_height", b"oem_icon_height", "oem_icon_width", b"oem_icon_width", "oem_local_config", b"oem_local_config", "oem_local_module_config", b"oem_local_module_config", "oem_text", b"oem_text"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["channels", b"channels", "config", b"config", "module_config", b"module_config", "owner", b"owner"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["channels", b"channels", "config", b"config", "module_config", b"module_config", "owner", b"owner", "timestamp", b"timestamp", "version", b"version"]) -> None: ...
|
||||
|
||||
global___OEMStore = OEMStore
|
||||
global___BackupPreferences = BackupPreferences
|
||||
|
||||
8
meshtastic/protobuf/localonly_pb2.py
generated
8
meshtastic/protobuf/localonly_pb2.py
generated
@@ -15,7 +15,7 @@ from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config
|
||||
from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/localonly.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xbc\x03\n\x0bLocalConfig\x12\x38\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfig\x12<\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfig\x12\x36\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfig\x12:\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfig\x12:\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfig\x12\x34\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfig\x12>\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\"\xf0\x07\n\x11LocalModuleConfig\x12:\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfig\x12>\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfig\x12[\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfig\x12K\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfig\x12\x45\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfig\x12\x44\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfig\x12M\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfig\x12<\n\x05\x61udio\x18\t \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfig\x12O\n\x0fremote_hardware\x18\n \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfig\x12K\n\rneighbor_info\x18\x0b \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfig\x12Q\n\x10\x61mbient_lighting\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfig\x12Q\n\x10\x64\x65tection_sensor\x18\r \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfig\x12\x46\n\npaxcounter\x18\x0e \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBd\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/localonly.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xfa\x03\n\x0bLocalConfig\x12\x38\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfig\x12<\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfig\x12\x36\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfig\x12:\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfig\x12:\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfig\x12\x34\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfig\x12>\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\x12<\n\x08security\x18\t \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfig\"\xf0\x07\n\x11LocalModuleConfig\x12:\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfig\x12>\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfig\x12[\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfig\x12K\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfig\x12\x45\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfig\x12\x44\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfig\x12M\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfig\x12<\n\x05\x61udio\x18\t \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfig\x12O\n\x0fremote_hardware\x18\n \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfig\x12K\n\rneighbor_info\x18\x0b \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfig\x12Q\n\x10\x61mbient_lighting\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfig\x12Q\n\x10\x64\x65tection_sensor\x18\r \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfig\x12\x46\n\npaxcounter\x18\x0e \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBd\n\x13\x63om.geeksville.meshB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
@@ -24,7 +24,7 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_globals['_LOCALCONFIG']._serialized_start=136
|
||||
_globals['_LOCALCONFIG']._serialized_end=580
|
||||
_globals['_LOCALMODULECONFIG']._serialized_start=583
|
||||
_globals['_LOCALMODULECONFIG']._serialized_end=1591
|
||||
_globals['_LOCALCONFIG']._serialized_end=642
|
||||
_globals['_LOCALMODULECONFIG']._serialized_start=645
|
||||
_globals['_LOCALMODULECONFIG']._serialized_end=1653
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
||||
12
meshtastic/protobuf/localonly_pb2.pyi
generated
12
meshtastic/protobuf/localonly_pb2.pyi
generated
@@ -29,6 +29,7 @@ class LocalConfig(google.protobuf.message.Message):
|
||||
LORA_FIELD_NUMBER: builtins.int
|
||||
BLUETOOTH_FIELD_NUMBER: builtins.int
|
||||
VERSION_FIELD_NUMBER: builtins.int
|
||||
SECURITY_FIELD_NUMBER: builtins.int
|
||||
version: builtins.int
|
||||
"""
|
||||
A version integer used to invalidate old save files when we make
|
||||
@@ -77,6 +78,12 @@ class LocalConfig(google.protobuf.message.Message):
|
||||
The part of the config that is specific to the Bluetooth settings
|
||||
"""
|
||||
|
||||
@property
|
||||
def security(self) -> meshtastic.protobuf.config_pb2.Config.SecurityConfig:
|
||||
"""
|
||||
The part of the config that is specific to Security settings
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -88,9 +95,10 @@ class LocalConfig(google.protobuf.message.Message):
|
||||
lora: meshtastic.protobuf.config_pb2.Config.LoRaConfig | None = ...,
|
||||
bluetooth: meshtastic.protobuf.config_pb2.Config.BluetoothConfig | None = ...,
|
||||
version: builtins.int = ...,
|
||||
security: meshtastic.protobuf.config_pb2.Config.SecurityConfig | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "position", b"position", "power", b"power"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "position", b"position", "power", b"power", "version", b"version"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "position", b"position", "power", b"power", "security", b"security"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["bluetooth", b"bluetooth", "device", b"device", "display", b"display", "lora", b"lora", "network", b"network", "position", b"position", "power", b"power", "security", b"security", "version", b"version"]) -> None: ...
|
||||
|
||||
global___LocalConfig = LocalConfig
|
||||
|
||||
|
||||
139
meshtastic/protobuf/mesh_pb2.py
generated
139
meshtastic/protobuf/mesh_pb2.py
generated
File diff suppressed because one or more lines are too long
552
meshtastic/protobuf/mesh_pb2.pyi
generated
552
meshtastic/protobuf/mesh_pb2.pyi
generated
@@ -11,6 +11,7 @@ import google.protobuf.internal.enum_type_wrapper
|
||||
import google.protobuf.message
|
||||
import meshtastic.protobuf.channel_pb2
|
||||
import meshtastic.protobuf.config_pb2
|
||||
import meshtastic.protobuf.device_ui_pb2
|
||||
import meshtastic.protobuf.module_config_pb2
|
||||
import meshtastic.protobuf.portnums_pb2
|
||||
import meshtastic.protobuf.telemetry_pb2
|
||||
@@ -129,6 +130,10 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
|
||||
"""
|
||||
Heltec HRU-3601: https://heltec.org/project/hru-3601/
|
||||
"""
|
||||
HELTEC_WIRELESS_BRIDGE: _HardwareModel.ValueType # 24
|
||||
"""
|
||||
Heltec Wireless Bridge
|
||||
"""
|
||||
STATION_G1: _HardwareModel.ValueType # 25
|
||||
"""
|
||||
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
@@ -201,7 +206,7 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
|
||||
"""
|
||||
M5STACK: _HardwareModel.ValueType # 42
|
||||
"""
|
||||
M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/
|
||||
M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/
|
||||
"""
|
||||
HELTEC_V3: _HardwareModel.ValueType # 43
|
||||
"""
|
||||
@@ -345,6 +350,58 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
|
||||
RadioMaster 900 Bandit, https://www.radiomasterrc.com/products/bandit-expresslrs-rf-module
|
||||
SSD1306 OLED and No GPS
|
||||
"""
|
||||
ME25LS01_4Y10TD: _HardwareModel.ValueType # 75
|
||||
"""
|
||||
Minewsemi ME25LS01 (ME25LE01_V1.0). NRF52840 w/ LR1110 radio, buttons and leds and pins.
|
||||
"""
|
||||
RP2040_FEATHER_RFM95: _HardwareModel.ValueType # 76
|
||||
"""
|
||||
RP2040_FEATHER_RFM95
|
||||
Adafruit Feather RP2040 with RFM95 LoRa Radio RFM95 with SX1272, SSD1306 OLED
|
||||
https://www.adafruit.com/product/5714
|
||||
https://www.adafruit.com/product/326
|
||||
https://www.adafruit.com/product/938
|
||||
^^^ short A0 to switch to I2C address 0x3C
|
||||
"""
|
||||
M5STACK_COREBASIC: _HardwareModel.ValueType # 77
|
||||
"""M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/"""
|
||||
M5STACK_CORE2: _HardwareModel.ValueType # 78
|
||||
RPI_PICO2: _HardwareModel.ValueType # 79
|
||||
"""Pico2 with Waveshare Hat, same as Pico"""
|
||||
M5STACK_CORES3: _HardwareModel.ValueType # 80
|
||||
"""M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/"""
|
||||
SEEED_XIAO_S3: _HardwareModel.ValueType # 81
|
||||
"""Seeed XIAO S3 DK"""
|
||||
MS24SF1: _HardwareModel.ValueType # 82
|
||||
"""
|
||||
Nordic nRF52840+Semtech SX1262 LoRa BLE Combo Module. nRF52840+SX1262 MS24SF1
|
||||
"""
|
||||
TLORA_C6: _HardwareModel.ValueType # 83
|
||||
"""
|
||||
Lilygo TLora-C6 with the new ESP32-C6 MCU
|
||||
"""
|
||||
WISMESH_TAP: _HardwareModel.ValueType # 84
|
||||
"""
|
||||
WisMesh Tap
|
||||
RAK-4631 w/ TFT in injection modled case
|
||||
"""
|
||||
ROUTASTIC: _HardwareModel.ValueType # 85
|
||||
"""
|
||||
Similar to PORTDUINO but used by Routastic devices, this is not any
|
||||
particular device and does not run Meshtastic's code but supports
|
||||
the same frame format.
|
||||
Runs on linux, see https://github.com/Jorropo/routastic
|
||||
"""
|
||||
MESH_TAB: _HardwareModel.ValueType # 86
|
||||
"""
|
||||
Mesh-Tab, esp32 based
|
||||
https://github.com/valzzu/Mesh-Tab
|
||||
"""
|
||||
MESHLINK: _HardwareModel.ValueType # 87
|
||||
"""
|
||||
MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog
|
||||
https://www.loraitalia.it
|
||||
"""
|
||||
PRIVATE_HW: _HardwareModel.ValueType # 255
|
||||
"""
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -458,6 +515,10 @@ HELTEC_HRU_3601: HardwareModel.ValueType # 23
|
||||
"""
|
||||
Heltec HRU-3601: https://heltec.org/project/hru-3601/
|
||||
"""
|
||||
HELTEC_WIRELESS_BRIDGE: HardwareModel.ValueType # 24
|
||||
"""
|
||||
Heltec Wireless Bridge
|
||||
"""
|
||||
STATION_G1: HardwareModel.ValueType # 25
|
||||
"""
|
||||
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
@@ -530,7 +591,7 @@ Custom Disaster Radio esp32 v3 device https://github.com/sudomesh/disaster-radio
|
||||
"""
|
||||
M5STACK: HardwareModel.ValueType # 42
|
||||
"""
|
||||
M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/
|
||||
M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/
|
||||
"""
|
||||
HELTEC_V3: HardwareModel.ValueType # 43
|
||||
"""
|
||||
@@ -674,6 +735,58 @@ RADIOMASTER_900_BANDIT: HardwareModel.ValueType # 74
|
||||
RadioMaster 900 Bandit, https://www.radiomasterrc.com/products/bandit-expresslrs-rf-module
|
||||
SSD1306 OLED and No GPS
|
||||
"""
|
||||
ME25LS01_4Y10TD: HardwareModel.ValueType # 75
|
||||
"""
|
||||
Minewsemi ME25LS01 (ME25LE01_V1.0). NRF52840 w/ LR1110 radio, buttons and leds and pins.
|
||||
"""
|
||||
RP2040_FEATHER_RFM95: HardwareModel.ValueType # 76
|
||||
"""
|
||||
RP2040_FEATHER_RFM95
|
||||
Adafruit Feather RP2040 with RFM95 LoRa Radio RFM95 with SX1272, SSD1306 OLED
|
||||
https://www.adafruit.com/product/5714
|
||||
https://www.adafruit.com/product/326
|
||||
https://www.adafruit.com/product/938
|
||||
^^^ short A0 to switch to I2C address 0x3C
|
||||
"""
|
||||
M5STACK_COREBASIC: HardwareModel.ValueType # 77
|
||||
"""M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/"""
|
||||
M5STACK_CORE2: HardwareModel.ValueType # 78
|
||||
RPI_PICO2: HardwareModel.ValueType # 79
|
||||
"""Pico2 with Waveshare Hat, same as Pico"""
|
||||
M5STACK_CORES3: HardwareModel.ValueType # 80
|
||||
"""M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, CoreS3, Paper) https://m5stack.com/"""
|
||||
SEEED_XIAO_S3: HardwareModel.ValueType # 81
|
||||
"""Seeed XIAO S3 DK"""
|
||||
MS24SF1: HardwareModel.ValueType # 82
|
||||
"""
|
||||
Nordic nRF52840+Semtech SX1262 LoRa BLE Combo Module. nRF52840+SX1262 MS24SF1
|
||||
"""
|
||||
TLORA_C6: HardwareModel.ValueType # 83
|
||||
"""
|
||||
Lilygo TLora-C6 with the new ESP32-C6 MCU
|
||||
"""
|
||||
WISMESH_TAP: HardwareModel.ValueType # 84
|
||||
"""
|
||||
WisMesh Tap
|
||||
RAK-4631 w/ TFT in injection modled case
|
||||
"""
|
||||
ROUTASTIC: HardwareModel.ValueType # 85
|
||||
"""
|
||||
Similar to PORTDUINO but used by Routastic devices, this is not any
|
||||
particular device and does not run Meshtastic's code but supports
|
||||
the same frame format.
|
||||
Runs on linux, see https://github.com/Jorropo/routastic
|
||||
"""
|
||||
MESH_TAB: HardwareModel.ValueType # 86
|
||||
"""
|
||||
Mesh-Tab, esp32 based
|
||||
https://github.com/valzzu/Mesh-Tab
|
||||
"""
|
||||
MESHLINK: HardwareModel.ValueType # 87
|
||||
"""
|
||||
MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog
|
||||
https://www.loraitalia.it
|
||||
"""
|
||||
PRIVATE_HW: HardwareModel.ValueType # 255
|
||||
"""
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -693,7 +806,7 @@ class _ConstantsEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._Enum
|
||||
First enum must be zero, and we are just using this enum to
|
||||
pass int constants between two very different environments
|
||||
"""
|
||||
DATA_PAYLOAD_LEN: _Constants.ValueType # 237
|
||||
DATA_PAYLOAD_LEN: _Constants.ValueType # 233
|
||||
"""
|
||||
From mesh.options
|
||||
note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is
|
||||
@@ -710,7 +823,7 @@ ZERO: Constants.ValueType # 0
|
||||
First enum must be zero, and we are just using this enum to
|
||||
pass int constants between two very different environments
|
||||
"""
|
||||
DATA_PAYLOAD_LEN: Constants.ValueType # 237
|
||||
DATA_PAYLOAD_LEN: Constants.ValueType # 233
|
||||
"""
|
||||
From mesh.options
|
||||
note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is
|
||||
@@ -855,10 +968,138 @@ If you see this failure in the field please post in the forum because we are int
|
||||
"""
|
||||
global___CriticalErrorCode = CriticalErrorCode
|
||||
|
||||
class _ExcludedModules:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _ExcludedModulesEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_ExcludedModules.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
EXCLUDED_NONE: _ExcludedModules.ValueType # 0
|
||||
"""
|
||||
Default value of 0 indicates no modules are excluded.
|
||||
"""
|
||||
MQTT_CONFIG: _ExcludedModules.ValueType # 1
|
||||
"""
|
||||
MQTT module
|
||||
"""
|
||||
SERIAL_CONFIG: _ExcludedModules.ValueType # 2
|
||||
"""
|
||||
Serial module
|
||||
"""
|
||||
EXTNOTIF_CONFIG: _ExcludedModules.ValueType # 4
|
||||
"""
|
||||
External Notification module
|
||||
"""
|
||||
STOREFORWARD_CONFIG: _ExcludedModules.ValueType # 8
|
||||
"""
|
||||
Store and Forward module
|
||||
"""
|
||||
RANGETEST_CONFIG: _ExcludedModules.ValueType # 16
|
||||
"""
|
||||
Range Test module
|
||||
"""
|
||||
TELEMETRY_CONFIG: _ExcludedModules.ValueType # 32
|
||||
"""
|
||||
Telemetry module
|
||||
"""
|
||||
CANNEDMSG_CONFIG: _ExcludedModules.ValueType # 64
|
||||
"""
|
||||
Canned Message module
|
||||
"""
|
||||
AUDIO_CONFIG: _ExcludedModules.ValueType # 128
|
||||
"""
|
||||
Audio module
|
||||
"""
|
||||
REMOTEHARDWARE_CONFIG: _ExcludedModules.ValueType # 256
|
||||
"""
|
||||
Remote Hardware module
|
||||
"""
|
||||
NEIGHBORINFO_CONFIG: _ExcludedModules.ValueType # 512
|
||||
"""
|
||||
Neighbor Info module
|
||||
"""
|
||||
AMBIENTLIGHTING_CONFIG: _ExcludedModules.ValueType # 1024
|
||||
"""
|
||||
Ambient Lighting module
|
||||
"""
|
||||
DETECTIONSENSOR_CONFIG: _ExcludedModules.ValueType # 2048
|
||||
"""
|
||||
Detection Sensor module
|
||||
"""
|
||||
PAXCOUNTER_CONFIG: _ExcludedModules.ValueType # 4096
|
||||
"""
|
||||
Paxcounter module
|
||||
"""
|
||||
|
||||
class ExcludedModules(_ExcludedModules, metaclass=_ExcludedModulesEnumTypeWrapper):
|
||||
"""
|
||||
Enum for modules excluded from a device's configuration.
|
||||
Each value represents a ModuleConfigType that can be toggled as excluded
|
||||
by setting its corresponding bit in the `excluded_modules` bitmask field.
|
||||
"""
|
||||
|
||||
EXCLUDED_NONE: ExcludedModules.ValueType # 0
|
||||
"""
|
||||
Default value of 0 indicates no modules are excluded.
|
||||
"""
|
||||
MQTT_CONFIG: ExcludedModules.ValueType # 1
|
||||
"""
|
||||
MQTT module
|
||||
"""
|
||||
SERIAL_CONFIG: ExcludedModules.ValueType # 2
|
||||
"""
|
||||
Serial module
|
||||
"""
|
||||
EXTNOTIF_CONFIG: ExcludedModules.ValueType # 4
|
||||
"""
|
||||
External Notification module
|
||||
"""
|
||||
STOREFORWARD_CONFIG: ExcludedModules.ValueType # 8
|
||||
"""
|
||||
Store and Forward module
|
||||
"""
|
||||
RANGETEST_CONFIG: ExcludedModules.ValueType # 16
|
||||
"""
|
||||
Range Test module
|
||||
"""
|
||||
TELEMETRY_CONFIG: ExcludedModules.ValueType # 32
|
||||
"""
|
||||
Telemetry module
|
||||
"""
|
||||
CANNEDMSG_CONFIG: ExcludedModules.ValueType # 64
|
||||
"""
|
||||
Canned Message module
|
||||
"""
|
||||
AUDIO_CONFIG: ExcludedModules.ValueType # 128
|
||||
"""
|
||||
Audio module
|
||||
"""
|
||||
REMOTEHARDWARE_CONFIG: ExcludedModules.ValueType # 256
|
||||
"""
|
||||
Remote Hardware module
|
||||
"""
|
||||
NEIGHBORINFO_CONFIG: ExcludedModules.ValueType # 512
|
||||
"""
|
||||
Neighbor Info module
|
||||
"""
|
||||
AMBIENTLIGHTING_CONFIG: ExcludedModules.ValueType # 1024
|
||||
"""
|
||||
Ambient Lighting module
|
||||
"""
|
||||
DETECTIONSENSOR_CONFIG: ExcludedModules.ValueType # 2048
|
||||
"""
|
||||
Detection Sensor module
|
||||
"""
|
||||
PAXCOUNTER_CONFIG: ExcludedModules.ValueType # 4096
|
||||
"""
|
||||
Paxcounter module
|
||||
"""
|
||||
global___ExcludedModules = ExcludedModules
|
||||
|
||||
@typing.final
|
||||
class Position(google.protobuf.message.Message):
|
||||
"""
|
||||
a gps position
|
||||
A GPS Position
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
@@ -1099,22 +1340,22 @@ class Position(google.protobuf.message.Message):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
latitude_i: builtins.int = ...,
|
||||
longitude_i: builtins.int = ...,
|
||||
altitude: builtins.int = ...,
|
||||
latitude_i: builtins.int | None = ...,
|
||||
longitude_i: builtins.int | None = ...,
|
||||
altitude: builtins.int | None = ...,
|
||||
time: builtins.int = ...,
|
||||
location_source: global___Position.LocSource.ValueType = ...,
|
||||
altitude_source: global___Position.AltSource.ValueType = ...,
|
||||
timestamp: builtins.int = ...,
|
||||
timestamp_millis_adjust: builtins.int = ...,
|
||||
altitude_hae: builtins.int = ...,
|
||||
altitude_geoidal_separation: builtins.int = ...,
|
||||
altitude_hae: builtins.int | None = ...,
|
||||
altitude_geoidal_separation: builtins.int | None = ...,
|
||||
PDOP: builtins.int = ...,
|
||||
HDOP: builtins.int = ...,
|
||||
VDOP: builtins.int = ...,
|
||||
gps_accuracy: builtins.int = ...,
|
||||
ground_speed: builtins.int = ...,
|
||||
ground_track: builtins.int = ...,
|
||||
ground_speed: builtins.int | None = ...,
|
||||
ground_track: builtins.int | None = ...,
|
||||
fix_quality: builtins.int = ...,
|
||||
fix_type: builtins.int = ...,
|
||||
sats_in_view: builtins.int = ...,
|
||||
@@ -1123,7 +1364,22 @@ class Position(google.protobuf.message.Message):
|
||||
seq_number: builtins.int = ...,
|
||||
precision_bits: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["HDOP", b"HDOP", "PDOP", b"PDOP", "VDOP", b"VDOP", "altitude", b"altitude", "altitude_geoidal_separation", b"altitude_geoidal_separation", "altitude_hae", b"altitude_hae", "altitude_source", b"altitude_source", "fix_quality", b"fix_quality", "fix_type", b"fix_type", "gps_accuracy", b"gps_accuracy", "ground_speed", b"ground_speed", "ground_track", b"ground_track", "latitude_i", b"latitude_i", "location_source", b"location_source", "longitude_i", b"longitude_i", "next_update", b"next_update", "precision_bits", b"precision_bits", "sats_in_view", b"sats_in_view", "sensor_id", b"sensor_id", "seq_number", b"seq_number", "time", b"time", "timestamp", b"timestamp", "timestamp_millis_adjust", b"timestamp_millis_adjust"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_altitude", b"_altitude", "_altitude_geoidal_separation", b"_altitude_geoidal_separation", "_altitude_hae", b"_altitude_hae", "_ground_speed", b"_ground_speed", "_ground_track", b"_ground_track", "_latitude_i", b"_latitude_i", "_longitude_i", b"_longitude_i", "altitude", b"altitude", "altitude_geoidal_separation", b"altitude_geoidal_separation", "altitude_hae", b"altitude_hae", "ground_speed", b"ground_speed", "ground_track", b"ground_track", "latitude_i", b"latitude_i", "longitude_i", b"longitude_i"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["HDOP", b"HDOP", "PDOP", b"PDOP", "VDOP", b"VDOP", "_altitude", b"_altitude", "_altitude_geoidal_separation", b"_altitude_geoidal_separation", "_altitude_hae", b"_altitude_hae", "_ground_speed", b"_ground_speed", "_ground_track", b"_ground_track", "_latitude_i", b"_latitude_i", "_longitude_i", b"_longitude_i", "altitude", b"altitude", "altitude_geoidal_separation", b"altitude_geoidal_separation", "altitude_hae", b"altitude_hae", "altitude_source", b"altitude_source", "fix_quality", b"fix_quality", "fix_type", b"fix_type", "gps_accuracy", b"gps_accuracy", "ground_speed", b"ground_speed", "ground_track", b"ground_track", "latitude_i", b"latitude_i", "location_source", b"location_source", "longitude_i", b"longitude_i", "next_update", b"next_update", "precision_bits", b"precision_bits", "sats_in_view", b"sats_in_view", "sensor_id", b"sensor_id", "seq_number", b"seq_number", "time", b"time", "timestamp", b"timestamp", "timestamp_millis_adjust", b"timestamp_millis_adjust"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_altitude", b"_altitude"]) -> typing.Literal["altitude"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_altitude_geoidal_separation", b"_altitude_geoidal_separation"]) -> typing.Literal["altitude_geoidal_separation"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_altitude_hae", b"_altitude_hae"]) -> typing.Literal["altitude_hae"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ground_speed", b"_ground_speed"]) -> typing.Literal["ground_speed"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ground_track", b"_ground_track"]) -> typing.Literal["ground_track"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_latitude_i", b"_latitude_i"]) -> typing.Literal["latitude_i"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_longitude_i", b"_longitude_i"]) -> typing.Literal["longitude_i"] | None: ...
|
||||
|
||||
global___Position = Position
|
||||
|
||||
@@ -1161,6 +1417,7 @@ class User(google.protobuf.message.Message):
|
||||
HW_MODEL_FIELD_NUMBER: builtins.int
|
||||
IS_LICENSED_FIELD_NUMBER: builtins.int
|
||||
ROLE_FIELD_NUMBER: builtins.int
|
||||
PUBLIC_KEY_FIELD_NUMBER: builtins.int
|
||||
id: builtins.str
|
||||
"""
|
||||
A globally unique ID string for this user.
|
||||
@@ -1200,6 +1457,11 @@ class User(google.protobuf.message.Message):
|
||||
"""
|
||||
Indicates that the user's role in the mesh
|
||||
"""
|
||||
public_key: builtins.bytes
|
||||
"""
|
||||
The public key of the user's device.
|
||||
This is sent out to other nodes on the mesh to allow them to compute a shared secret key.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -1210,32 +1472,57 @@ class User(google.protobuf.message.Message):
|
||||
hw_model: global___HardwareModel.ValueType = ...,
|
||||
is_licensed: builtins.bool = ...,
|
||||
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
|
||||
public_key: builtins.bytes = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["hw_model", b"hw_model", "id", b"id", "is_licensed", b"is_licensed", "long_name", b"long_name", "macaddr", b"macaddr", "role", b"role", "short_name", b"short_name"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["hw_model", b"hw_model", "id", b"id", "is_licensed", b"is_licensed", "long_name", b"long_name", "macaddr", b"macaddr", "public_key", b"public_key", "role", b"role", "short_name", b"short_name"]) -> None: ...
|
||||
|
||||
global___User = User
|
||||
|
||||
@typing.final
|
||||
class RouteDiscovery(google.protobuf.message.Message):
|
||||
"""
|
||||
A message used in our Dynamic Source Routing protocol (RFC 4728 based)
|
||||
A message used in a traceroute
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
ROUTE_FIELD_NUMBER: builtins.int
|
||||
SNR_TOWARDS_FIELD_NUMBER: builtins.int
|
||||
ROUTE_BACK_FIELD_NUMBER: builtins.int
|
||||
SNR_BACK_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def route(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]:
|
||||
"""
|
||||
The list of nodenums this packet has visited so far
|
||||
The list of nodenums this packet has visited so far to the destination.
|
||||
"""
|
||||
|
||||
@property
|
||||
def snr_towards(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]:
|
||||
"""
|
||||
The list of SNRs (in dB, scaled by 4) in the route towards the destination.
|
||||
"""
|
||||
|
||||
@property
|
||||
def route_back(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]:
|
||||
"""
|
||||
The list of nodenums the packet has visited on the way back from the destination.
|
||||
"""
|
||||
|
||||
@property
|
||||
def snr_back(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]:
|
||||
"""
|
||||
The list of SNRs (in dB, scaled by 4) in the route back from the destination.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
route: collections.abc.Iterable[builtins.int] | None = ...,
|
||||
snr_towards: collections.abc.Iterable[builtins.int] | None = ...,
|
||||
route_back: collections.abc.Iterable[builtins.int] | None = ...,
|
||||
snr_back: collections.abc.Iterable[builtins.int] | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["route", b"route"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["route", b"route", "route_back", b"route_back", "snr_back", b"snr_back", "snr_towards", b"snr_towards"]) -> None: ...
|
||||
|
||||
global___RouteDiscovery = RouteDiscovery
|
||||
|
||||
@@ -1303,6 +1590,22 @@ class Routing(google.protobuf.message.Message):
|
||||
The application layer service on the remote node received your request, but considered your request not authorized
|
||||
(i.e you did not send the request on the required bound channel)
|
||||
"""
|
||||
PKI_FAILED: Routing._Error.ValueType # 34
|
||||
"""
|
||||
The client specified a PKI transport, but the node was unable to send the packet using PKI (and did not send the message at all)
|
||||
"""
|
||||
PKI_UNKNOWN_PUBKEY: Routing._Error.ValueType # 35
|
||||
"""
|
||||
The receiving node does not have a Public Key to decode with
|
||||
"""
|
||||
ADMIN_BAD_SESSION_KEY: Routing._Error.ValueType # 36
|
||||
"""
|
||||
Admin packet otherwise checks out, but uses a bogus or expired session key
|
||||
"""
|
||||
ADMIN_PUBLIC_KEY_UNAUTHORIZED: Routing._Error.ValueType # 37
|
||||
"""
|
||||
Admin packet sent using PKC, but not from a public key on the admin key list
|
||||
"""
|
||||
|
||||
class Error(_Error, metaclass=_ErrorEnumTypeWrapper):
|
||||
"""
|
||||
@@ -1360,6 +1663,22 @@ class Routing(google.protobuf.message.Message):
|
||||
The application layer service on the remote node received your request, but considered your request not authorized
|
||||
(i.e you did not send the request on the required bound channel)
|
||||
"""
|
||||
PKI_FAILED: Routing.Error.ValueType # 34
|
||||
"""
|
||||
The client specified a PKI transport, but the node was unable to send the packet using PKI (and did not send the message at all)
|
||||
"""
|
||||
PKI_UNKNOWN_PUBKEY: Routing.Error.ValueType # 35
|
||||
"""
|
||||
The receiving node does not have a Public Key to decode with
|
||||
"""
|
||||
ADMIN_BAD_SESSION_KEY: Routing.Error.ValueType # 36
|
||||
"""
|
||||
Admin packet otherwise checks out, but uses a bogus or expired session key
|
||||
"""
|
||||
ADMIN_PUBLIC_KEY_UNAUTHORIZED: Routing.Error.ValueType # 37
|
||||
"""
|
||||
Admin packet sent using PKC, but not from a public key on the admin key list
|
||||
"""
|
||||
|
||||
ROUTE_REQUEST_FIELD_NUMBER: builtins.int
|
||||
ROUTE_REPLY_FIELD_NUMBER: builtins.int
|
||||
@@ -1412,6 +1731,7 @@ class Data(google.protobuf.message.Message):
|
||||
REQUEST_ID_FIELD_NUMBER: builtins.int
|
||||
REPLY_ID_FIELD_NUMBER: builtins.int
|
||||
EMOJI_FIELD_NUMBER: builtins.int
|
||||
BITFIELD_FIELD_NUMBER: builtins.int
|
||||
portnum: meshtastic.protobuf.portnums_pb2.PortNum.ValueType
|
||||
"""
|
||||
Formerly named typ and of type Type
|
||||
@@ -1454,6 +1774,10 @@ class Data(google.protobuf.message.Message):
|
||||
Defaults to false. If true, then what is in the payload should be treated as an emoji like giving
|
||||
a message a heart or poop emoji.
|
||||
"""
|
||||
bitfield: builtins.int
|
||||
"""
|
||||
Bitfield for extra flags. First use is to indicate that user approves the packet being uploaded to MQTT.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -1465,8 +1789,11 @@ class Data(google.protobuf.message.Message):
|
||||
request_id: builtins.int = ...,
|
||||
reply_id: builtins.int = ...,
|
||||
emoji: builtins.int = ...,
|
||||
bitfield: builtins.int | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["dest", b"dest", "emoji", b"emoji", "payload", b"payload", "portnum", b"portnum", "reply_id", b"reply_id", "request_id", b"request_id", "source", b"source", "want_response", b"want_response"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_bitfield", b"_bitfield", "bitfield", b"bitfield"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_bitfield", b"_bitfield", "bitfield", b"bitfield", "dest", b"dest", "emoji", b"emoji", "payload", b"payload", "portnum", b"portnum", "reply_id", b"reply_id", "request_id", b"request_id", "source", b"source", "want_response", b"want_response"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_bitfield", b"_bitfield"]) -> typing.Literal["bitfield"] | None: ...
|
||||
|
||||
global___Data = Data
|
||||
|
||||
@@ -1523,15 +1850,20 @@ class Waypoint(google.protobuf.message.Message):
|
||||
self,
|
||||
*,
|
||||
id: builtins.int = ...,
|
||||
latitude_i: builtins.int = ...,
|
||||
longitude_i: builtins.int = ...,
|
||||
latitude_i: builtins.int | None = ...,
|
||||
longitude_i: builtins.int | None = ...,
|
||||
expire: builtins.int = ...,
|
||||
locked_to: builtins.int = ...,
|
||||
name: builtins.str = ...,
|
||||
description: builtins.str = ...,
|
||||
icon: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["description", b"description", "expire", b"expire", "icon", b"icon", "id", b"id", "latitude_i", b"latitude_i", "locked_to", b"locked_to", "longitude_i", b"longitude_i", "name", b"name"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_latitude_i", b"_latitude_i", "_longitude_i", b"_longitude_i", "latitude_i", b"latitude_i", "longitude_i", b"longitude_i"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_latitude_i", b"_latitude_i", "_longitude_i", b"_longitude_i", "description", b"description", "expire", b"expire", "icon", b"icon", "id", b"id", "latitude_i", b"latitude_i", "locked_to", b"locked_to", "longitude_i", b"longitude_i", "name", b"name"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_latitude_i", b"_latitude_i"]) -> typing.Literal["latitude_i"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_longitude_i", b"_longitude_i"]) -> typing.Literal["longitude_i"] | None: ...
|
||||
|
||||
global___Waypoint = Waypoint
|
||||
|
||||
@@ -1615,6 +1947,19 @@ class MeshPacket(google.protobuf.message.Message):
|
||||
If priority is unset but the message is marked as want_ack,
|
||||
assume it is important and use a slightly higher priority
|
||||
"""
|
||||
RESPONSE: MeshPacket._Priority.ValueType # 80
|
||||
"""
|
||||
If priority is unset but the packet is a response to a request, we want it to get there relatively quickly.
|
||||
Furthermore, responses stop relaying packets directed to a node early.
|
||||
"""
|
||||
HIGH: MeshPacket._Priority.ValueType # 100
|
||||
"""
|
||||
Higher priority for specific message types (portnums) to distinguish between other reliable packets.
|
||||
"""
|
||||
ALERT: MeshPacket._Priority.ValueType # 110
|
||||
"""
|
||||
Higher priority alert message used for critical alerts which take priority over other reliable packets.
|
||||
"""
|
||||
ACK: MeshPacket._Priority.ValueType # 120
|
||||
"""
|
||||
Ack/naks are sent with very high priority to ensure that retransmission
|
||||
@@ -1669,6 +2014,19 @@ class MeshPacket(google.protobuf.message.Message):
|
||||
If priority is unset but the message is marked as want_ack,
|
||||
assume it is important and use a slightly higher priority
|
||||
"""
|
||||
RESPONSE: MeshPacket.Priority.ValueType # 80
|
||||
"""
|
||||
If priority is unset but the packet is a response to a request, we want it to get there relatively quickly.
|
||||
Furthermore, responses stop relaying packets directed to a node early.
|
||||
"""
|
||||
HIGH: MeshPacket.Priority.ValueType # 100
|
||||
"""
|
||||
Higher priority for specific message types (portnums) to distinguish between other reliable packets.
|
||||
"""
|
||||
ALERT: MeshPacket.Priority.ValueType # 110
|
||||
"""
|
||||
Higher priority alert message used for critical alerts which take priority over other reliable packets.
|
||||
"""
|
||||
ACK: MeshPacket.Priority.ValueType # 120
|
||||
"""
|
||||
Ack/naks are sent with very high priority to ensure that retransmission
|
||||
@@ -1731,6 +2089,11 @@ class MeshPacket(google.protobuf.message.Message):
|
||||
DELAYED_FIELD_NUMBER: builtins.int
|
||||
VIA_MQTT_FIELD_NUMBER: builtins.int
|
||||
HOP_START_FIELD_NUMBER: builtins.int
|
||||
PUBLIC_KEY_FIELD_NUMBER: builtins.int
|
||||
PKI_ENCRYPTED_FIELD_NUMBER: builtins.int
|
||||
NEXT_HOP_FIELD_NUMBER: builtins.int
|
||||
RELAY_NODE_FIELD_NUMBER: builtins.int
|
||||
TX_AFTER_FIELD_NUMBER: builtins.int
|
||||
to: builtins.int
|
||||
"""
|
||||
The (immediate) destination for this packet
|
||||
@@ -1775,7 +2138,7 @@ class MeshPacket(google.protobuf.message.Message):
|
||||
"""
|
||||
hop_limit: builtins.int
|
||||
"""
|
||||
If unset treated as zero (no forwarding, send to adjacent nodes only)
|
||||
If unset treated as zero (no forwarding, send to direct neighbor nodes only)
|
||||
if 1, allow hopping through one node, etc...
|
||||
For our usecase real world topologies probably have a max of about 3.
|
||||
This field is normally placed into a few of bits in the header.
|
||||
@@ -1814,6 +2177,30 @@ class MeshPacket(google.protobuf.message.Message):
|
||||
Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header.
|
||||
When receiving a packet, the difference between hop_start and hop_limit gives how many hops it traveled.
|
||||
"""
|
||||
public_key: builtins.bytes
|
||||
"""
|
||||
Records the public key the packet was encrypted with, if applicable.
|
||||
"""
|
||||
pki_encrypted: builtins.bool
|
||||
"""
|
||||
Indicates whether the packet was en/decrypted using PKI
|
||||
"""
|
||||
next_hop: builtins.int
|
||||
"""
|
||||
Last byte of the node number of the node that should be used as the next hop in routing.
|
||||
Set by the firmware internally, clients are not supposed to set this.
|
||||
"""
|
||||
relay_node: builtins.int
|
||||
"""
|
||||
Last byte of the node number of the node that will relay/relayed this packet.
|
||||
Set by the firmware internally, clients are not supposed to set this.
|
||||
"""
|
||||
tx_after: builtins.int
|
||||
"""
|
||||
*Never* sent over the radio links.
|
||||
Timestamp after which this packet may be sent.
|
||||
Set by the firmware internally, clients are not supposed to set this.
|
||||
"""
|
||||
@property
|
||||
def decoded(self) -> global___Data:
|
||||
"""
|
||||
@@ -1837,9 +2224,14 @@ class MeshPacket(google.protobuf.message.Message):
|
||||
delayed: global___MeshPacket.Delayed.ValueType = ...,
|
||||
via_mqtt: builtins.bool = ...,
|
||||
hop_start: builtins.int = ...,
|
||||
public_key: builtins.bytes = ...,
|
||||
pki_encrypted: builtins.bool = ...,
|
||||
next_hop: builtins.int = ...,
|
||||
relay_node: builtins.int = ...,
|
||||
tx_after: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["decoded", b"decoded", "encrypted", b"encrypted", "payload_variant", b"payload_variant"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "decoded", b"decoded", "delayed", b"delayed", "encrypted", b"encrypted", "from", b"from", "hop_limit", b"hop_limit", "hop_start", b"hop_start", "id", b"id", "payload_variant", b"payload_variant", "priority", b"priority", "rx_rssi", b"rx_rssi", "rx_snr", b"rx_snr", "rx_time", b"rx_time", "to", b"to", "via_mqtt", b"via_mqtt", "want_ack", b"want_ack"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "decoded", b"decoded", "delayed", b"delayed", "encrypted", b"encrypted", "from", b"from", "hop_limit", b"hop_limit", "hop_start", b"hop_start", "id", b"id", "next_hop", b"next_hop", "payload_variant", b"payload_variant", "pki_encrypted", b"pki_encrypted", "priority", b"priority", "public_key", b"public_key", "relay_node", b"relay_node", "rx_rssi", b"rx_rssi", "rx_snr", b"rx_snr", "rx_time", b"rx_time", "to", b"to", "tx_after", b"tx_after", "via_mqtt", b"via_mqtt", "want_ack", b"want_ack"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["decoded", "encrypted"] | None: ...
|
||||
|
||||
global___MeshPacket = MeshPacket
|
||||
@@ -1877,6 +2269,7 @@ class NodeInfo(google.protobuf.message.Message):
|
||||
VIA_MQTT_FIELD_NUMBER: builtins.int
|
||||
HOPS_AWAY_FIELD_NUMBER: builtins.int
|
||||
IS_FAVORITE_FIELD_NUMBER: builtins.int
|
||||
IS_IGNORED_FIELD_NUMBER: builtins.int
|
||||
num: builtins.int
|
||||
"""
|
||||
The node number
|
||||
@@ -1890,7 +2283,7 @@ class NodeInfo(google.protobuf.message.Message):
|
||||
"""
|
||||
TODO: REMOVE/INTEGRATE
|
||||
Not currently used (till full DSR deployment?) Our current preferred node node for routing - might be the same as num if
|
||||
we are adjacent Or zero if we don't yet know a route to this node.
|
||||
we are direct neighbor or zero if we don't yet know a route to this node.
|
||||
fixed32 next_hop = 5;
|
||||
|
||||
|
||||
@@ -1906,13 +2299,18 @@ class NodeInfo(google.protobuf.message.Message):
|
||||
"""
|
||||
hops_away: builtins.int
|
||||
"""
|
||||
Number of hops away from us this node is (0 if adjacent)
|
||||
Number of hops away from us this node is (0 if direct neighbor)
|
||||
"""
|
||||
is_favorite: builtins.bool
|
||||
"""
|
||||
True if node is in our favorites list
|
||||
Persists between NodeDB internal clean ups
|
||||
"""
|
||||
is_ignored: builtins.bool
|
||||
"""
|
||||
True if node is in our ignored list
|
||||
Persists between NodeDB internal clean ups
|
||||
"""
|
||||
@property
|
||||
def user(self) -> global___User:
|
||||
"""
|
||||
@@ -1943,11 +2341,13 @@ class NodeInfo(google.protobuf.message.Message):
|
||||
device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ...,
|
||||
channel: builtins.int = ...,
|
||||
via_mqtt: builtins.bool = ...,
|
||||
hops_away: builtins.int = ...,
|
||||
hops_away: builtins.int | None = ...,
|
||||
is_favorite: builtins.bool = ...,
|
||||
is_ignored: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["device_metrics", b"device_metrics", "position", b"position", "user", b"user"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "last_heard", b"last_heard", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "position", b"position", "user", b"user"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "last_heard", b"last_heard", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_hops_away", b"_hops_away"]) -> typing.Literal["hops_away"] | None: ...
|
||||
|
||||
global___NodeInfo = NodeInfo
|
||||
|
||||
@@ -1964,6 +2364,8 @@ class MyNodeInfo(google.protobuf.message.Message):
|
||||
MY_NODE_NUM_FIELD_NUMBER: builtins.int
|
||||
REBOOT_COUNT_FIELD_NUMBER: builtins.int
|
||||
MIN_APP_VERSION_FIELD_NUMBER: builtins.int
|
||||
DEVICE_ID_FIELD_NUMBER: builtins.int
|
||||
PIO_ENV_FIELD_NUMBER: builtins.int
|
||||
my_node_num: builtins.int
|
||||
"""
|
||||
Tells the phone what our node number is, default starting value is
|
||||
@@ -1979,14 +2381,24 @@ class MyNodeInfo(google.protobuf.message.Message):
|
||||
The minimum app version that can talk to this device.
|
||||
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app
|
||||
"""
|
||||
device_id: builtins.bytes
|
||||
"""
|
||||
Unique hardware identifier for this device
|
||||
"""
|
||||
pio_env: builtins.str
|
||||
"""
|
||||
The PlatformIO environment used to build this firmware
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
my_node_num: builtins.int = ...,
|
||||
reboot_count: builtins.int = ...,
|
||||
min_app_version: builtins.int = ...,
|
||||
device_id: builtins.bytes = ...,
|
||||
pio_env: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["min_app_version", b"min_app_version", "my_node_num", b"my_node_num", "reboot_count", b"reboot_count"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["device_id", b"device_id", "min_app_version", b"min_app_version", "my_node_num", b"my_node_num", "pio_env", b"pio_env", "reboot_count", b"reboot_count"]) -> None: ...
|
||||
|
||||
global___MyNodeInfo = MyNodeInfo
|
||||
|
||||
@@ -2157,6 +2569,8 @@ class FromRadio(google.protobuf.message.Message):
|
||||
METADATA_FIELD_NUMBER: builtins.int
|
||||
MQTTCLIENTPROXYMESSAGE_FIELD_NUMBER: builtins.int
|
||||
FILEINFO_FIELD_NUMBER: builtins.int
|
||||
CLIENTNOTIFICATION_FIELD_NUMBER: builtins.int
|
||||
DEVICEUICONFIG_FIELD_NUMBER: builtins.int
|
||||
id: builtins.int
|
||||
"""
|
||||
The packet id, used to allow the phone to request missing read packets from the FIFO,
|
||||
@@ -2250,6 +2664,18 @@ class FromRadio(google.protobuf.message.Message):
|
||||
File system manifest messages
|
||||
"""
|
||||
|
||||
@property
|
||||
def clientNotification(self) -> global___ClientNotification:
|
||||
"""
|
||||
Notification message to the client
|
||||
"""
|
||||
|
||||
@property
|
||||
def deviceuiConfig(self) -> meshtastic.protobuf.device_ui_pb2.DeviceUIConfig:
|
||||
"""
|
||||
Persistent data for device-ui
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -2268,13 +2694,60 @@ class FromRadio(google.protobuf.message.Message):
|
||||
metadata: global___DeviceMetadata | None = ...,
|
||||
mqttClientProxyMessage: global___MqttClientProxyMessage | None = ...,
|
||||
fileInfo: global___FileInfo | None = ...,
|
||||
clientNotification: global___ClientNotification | None = ...,
|
||||
deviceuiConfig: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["channel", b"channel", "config", b"config", "config_complete_id", b"config_complete_id", "fileInfo", b"fileInfo", "log_record", b"log_record", "metadata", b"metadata", "moduleConfig", b"moduleConfig", "mqttClientProxyMessage", b"mqttClientProxyMessage", "my_info", b"my_info", "node_info", b"node_info", "packet", b"packet", "payload_variant", b"payload_variant", "queueStatus", b"queueStatus", "rebooted", b"rebooted", "xmodemPacket", b"xmodemPacket"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "config", b"config", "config_complete_id", b"config_complete_id", "fileInfo", b"fileInfo", "id", b"id", "log_record", b"log_record", "metadata", b"metadata", "moduleConfig", b"moduleConfig", "mqttClientProxyMessage", b"mqttClientProxyMessage", "my_info", b"my_info", "node_info", b"node_info", "packet", b"packet", "payload_variant", b"payload_variant", "queueStatus", b"queueStatus", "rebooted", b"rebooted", "xmodemPacket", b"xmodemPacket"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["packet", "my_info", "node_info", "config", "log_record", "config_complete_id", "rebooted", "moduleConfig", "channel", "queueStatus", "xmodemPacket", "metadata", "mqttClientProxyMessage", "fileInfo"] | None: ...
|
||||
def HasField(self, field_name: typing.Literal["channel", b"channel", "clientNotification", b"clientNotification", "config", b"config", "config_complete_id", b"config_complete_id", "deviceuiConfig", b"deviceuiConfig", "fileInfo", b"fileInfo", "log_record", b"log_record", "metadata", b"metadata", "moduleConfig", b"moduleConfig", "mqttClientProxyMessage", b"mqttClientProxyMessage", "my_info", b"my_info", "node_info", b"node_info", "packet", b"packet", "payload_variant", b"payload_variant", "queueStatus", b"queueStatus", "rebooted", b"rebooted", "xmodemPacket", b"xmodemPacket"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["channel", b"channel", "clientNotification", b"clientNotification", "config", b"config", "config_complete_id", b"config_complete_id", "deviceuiConfig", b"deviceuiConfig", "fileInfo", b"fileInfo", "id", b"id", "log_record", b"log_record", "metadata", b"metadata", "moduleConfig", b"moduleConfig", "mqttClientProxyMessage", b"mqttClientProxyMessage", "my_info", b"my_info", "node_info", b"node_info", "packet", b"packet", "payload_variant", b"payload_variant", "queueStatus", b"queueStatus", "rebooted", b"rebooted", "xmodemPacket", b"xmodemPacket"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["packet", "my_info", "node_info", "config", "log_record", "config_complete_id", "rebooted", "moduleConfig", "channel", "queueStatus", "xmodemPacket", "metadata", "mqttClientProxyMessage", "fileInfo", "clientNotification", "deviceuiConfig"] | None: ...
|
||||
|
||||
global___FromRadio = FromRadio
|
||||
|
||||
@typing.final
|
||||
class ClientNotification(google.protobuf.message.Message):
|
||||
"""
|
||||
A notification message from the device to the client
|
||||
To be used for important messages that should to be displayed to the user
|
||||
in the form of push notifications or validation messages when saving
|
||||
invalid configuration.
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
REPLY_ID_FIELD_NUMBER: builtins.int
|
||||
TIME_FIELD_NUMBER: builtins.int
|
||||
LEVEL_FIELD_NUMBER: builtins.int
|
||||
MESSAGE_FIELD_NUMBER: builtins.int
|
||||
reply_id: builtins.int
|
||||
"""
|
||||
The id of the packet we're notifying in response to
|
||||
"""
|
||||
time: builtins.int
|
||||
"""
|
||||
Seconds since 1970 - or 0 for unknown/unset
|
||||
"""
|
||||
level: global___LogRecord.Level.ValueType
|
||||
"""
|
||||
The level type of notification
|
||||
"""
|
||||
message: builtins.str
|
||||
"""
|
||||
The message body of the notification
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
reply_id: builtins.int | None = ...,
|
||||
time: builtins.int = ...,
|
||||
level: global___LogRecord.Level.ValueType = ...,
|
||||
message: builtins.str = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_reply_id", b"_reply_id", "reply_id", b"reply_id"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_reply_id", b"_reply_id", "level", b"level", "message", b"message", "reply_id", b"reply_id", "time", b"time"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_reply_id", b"_reply_id"]) -> typing.Literal["reply_id"] | None: ...
|
||||
|
||||
global___ClientNotification = ClientNotification
|
||||
|
||||
@typing.final
|
||||
class FileInfo(google.protobuf.message.Message):
|
||||
"""
|
||||
@@ -2505,6 +2978,8 @@ class DeviceMetadata(google.protobuf.message.Message):
|
||||
POSITION_FLAGS_FIELD_NUMBER: builtins.int
|
||||
HW_MODEL_FIELD_NUMBER: builtins.int
|
||||
HASREMOTEHARDWARE_FIELD_NUMBER: builtins.int
|
||||
HASPKC_FIELD_NUMBER: builtins.int
|
||||
EXCLUDED_MODULES_FIELD_NUMBER: builtins.int
|
||||
firmware_version: builtins.str
|
||||
"""
|
||||
Device firmware version string
|
||||
@@ -2545,6 +3020,15 @@ class DeviceMetadata(google.protobuf.message.Message):
|
||||
"""
|
||||
Has Remote Hardware enabled
|
||||
"""
|
||||
hasPKC: builtins.bool
|
||||
"""
|
||||
Has PKC capabilities
|
||||
"""
|
||||
excluded_modules: builtins.int
|
||||
"""
|
||||
Bit field of boolean for excluded modules
|
||||
(bitwise OR of ExcludedModules)
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -2558,8 +3042,10 @@ class DeviceMetadata(google.protobuf.message.Message):
|
||||
position_flags: builtins.int = ...,
|
||||
hw_model: global___HardwareModel.ValueType = ...,
|
||||
hasRemoteHardware: builtins.bool = ...,
|
||||
hasPKC: builtins.bool = ...,
|
||||
excluded_modules: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["canShutdown", b"canShutdown", "device_state_version", b"device_state_version", "firmware_version", b"firmware_version", "hasBluetooth", b"hasBluetooth", "hasEthernet", b"hasEthernet", "hasRemoteHardware", b"hasRemoteHardware", "hasWifi", b"hasWifi", "hw_model", b"hw_model", "position_flags", b"position_flags", "role", b"role"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["canShutdown", b"canShutdown", "device_state_version", b"device_state_version", "excluded_modules", b"excluded_modules", "firmware_version", b"firmware_version", "hasBluetooth", b"hasBluetooth", "hasEthernet", b"hasEthernet", "hasPKC", b"hasPKC", "hasRemoteHardware", b"hasRemoteHardware", "hasWifi", b"hasWifi", "hw_model", b"hw_model", "position_flags", b"position_flags", "role", b"role"]) -> None: ...
|
||||
|
||||
global___DeviceMetadata = DeviceMetadata
|
||||
|
||||
|
||||
72
meshtastic/protobuf/module_config_pb2.py
generated
72
meshtastic/protobuf/module_config_pb2.py
generated
File diff suppressed because one or more lines are too long
105
meshtastic/protobuf/module_config_pb2.pyi
generated
105
meshtastic/protobuf/module_config_pb2.pyi
generated
@@ -225,6 +225,7 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
|
||||
ENABLED_FIELD_NUMBER: builtins.int
|
||||
UPDATE_INTERVAL_FIELD_NUMBER: builtins.int
|
||||
TRANSMIT_OVER_LORA_FIELD_NUMBER: builtins.int
|
||||
enabled: builtins.bool
|
||||
"""
|
||||
Whether the Module is enabled
|
||||
@@ -232,15 +233,21 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
update_interval: builtins.int
|
||||
"""
|
||||
Interval in seconds of how often we should try to send our
|
||||
Neighbor Info to the mesh
|
||||
Neighbor Info (minimum is 14400, i.e., 4 hours)
|
||||
"""
|
||||
transmit_over_lora: builtins.bool
|
||||
"""
|
||||
Whether in addition to sending it to MQTT and the PhoneAPI, our NeighborInfo should be transmitted over LoRa.
|
||||
Note that this is not available on a channel with default key and name.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
enabled: builtins.bool = ...,
|
||||
update_interval: builtins.int = ...,
|
||||
transmit_over_lora: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["enabled", b"enabled", "update_interval", b"update_interval"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["enabled", b"enabled", "transmit_over_lora", b"transmit_over_lora", "update_interval", b"update_interval"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class DetectionSensorConfig(google.protobuf.message.Message):
|
||||
@@ -250,13 +257,54 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
class _TriggerType:
|
||||
ValueType = typing.NewType("ValueType", builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
|
||||
class _TriggerTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ModuleConfig.DetectionSensorConfig._TriggerType.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
LOGIC_LOW: ModuleConfig.DetectionSensorConfig._TriggerType.ValueType # 0
|
||||
"""Event is triggered if pin is low"""
|
||||
LOGIC_HIGH: ModuleConfig.DetectionSensorConfig._TriggerType.ValueType # 1
|
||||
"""Event is triggered if pin is high"""
|
||||
FALLING_EDGE: ModuleConfig.DetectionSensorConfig._TriggerType.ValueType # 2
|
||||
"""Event is triggered when pin goes high to low"""
|
||||
RISING_EDGE: ModuleConfig.DetectionSensorConfig._TriggerType.ValueType # 3
|
||||
"""Event is triggered when pin goes low to high"""
|
||||
EITHER_EDGE_ACTIVE_LOW: ModuleConfig.DetectionSensorConfig._TriggerType.ValueType # 4
|
||||
"""Event is triggered on every pin state change, low is considered to be
|
||||
"active"
|
||||
"""
|
||||
EITHER_EDGE_ACTIVE_HIGH: ModuleConfig.DetectionSensorConfig._TriggerType.ValueType # 5
|
||||
"""Event is triggered on every pin state change, high is considered to be
|
||||
"active"
|
||||
"""
|
||||
|
||||
class TriggerType(_TriggerType, metaclass=_TriggerTypeEnumTypeWrapper): ...
|
||||
LOGIC_LOW: ModuleConfig.DetectionSensorConfig.TriggerType.ValueType # 0
|
||||
"""Event is triggered if pin is low"""
|
||||
LOGIC_HIGH: ModuleConfig.DetectionSensorConfig.TriggerType.ValueType # 1
|
||||
"""Event is triggered if pin is high"""
|
||||
FALLING_EDGE: ModuleConfig.DetectionSensorConfig.TriggerType.ValueType # 2
|
||||
"""Event is triggered when pin goes high to low"""
|
||||
RISING_EDGE: ModuleConfig.DetectionSensorConfig.TriggerType.ValueType # 3
|
||||
"""Event is triggered when pin goes low to high"""
|
||||
EITHER_EDGE_ACTIVE_LOW: ModuleConfig.DetectionSensorConfig.TriggerType.ValueType # 4
|
||||
"""Event is triggered on every pin state change, low is considered to be
|
||||
"active"
|
||||
"""
|
||||
EITHER_EDGE_ACTIVE_HIGH: ModuleConfig.DetectionSensorConfig.TriggerType.ValueType # 5
|
||||
"""Event is triggered on every pin state change, high is considered to be
|
||||
"active"
|
||||
"""
|
||||
|
||||
ENABLED_FIELD_NUMBER: builtins.int
|
||||
MINIMUM_BROADCAST_SECS_FIELD_NUMBER: builtins.int
|
||||
STATE_BROADCAST_SECS_FIELD_NUMBER: builtins.int
|
||||
SEND_BELL_FIELD_NUMBER: builtins.int
|
||||
NAME_FIELD_NUMBER: builtins.int
|
||||
MONITOR_PIN_FIELD_NUMBER: builtins.int
|
||||
DETECTION_TRIGGERED_HIGH_FIELD_NUMBER: builtins.int
|
||||
DETECTION_TRIGGER_TYPE_FIELD_NUMBER: builtins.int
|
||||
USE_PULLUP_FIELD_NUMBER: builtins.int
|
||||
enabled: builtins.bool
|
||||
"""
|
||||
@@ -264,13 +312,15 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
"""
|
||||
minimum_broadcast_secs: builtins.int
|
||||
"""
|
||||
Interval in seconds of how often we can send a message to the mesh when a state change is detected
|
||||
Interval in seconds of how often we can send a message to the mesh when a
|
||||
trigger event is detected
|
||||
"""
|
||||
state_broadcast_secs: builtins.int
|
||||
"""
|
||||
Interval in seconds of how often we should send a message to the mesh with the current state regardless of changes
|
||||
When set to 0, only state changes will be broadcasted
|
||||
Works as a sort of status heartbeat for peace of mind
|
||||
Interval in seconds of how often we should send a message to the mesh
|
||||
with the current state regardless of trigger events When set to 0, only
|
||||
trigger events will be broadcasted Works as a sort of status heartbeat
|
||||
for peace of mind
|
||||
"""
|
||||
send_bell: builtins.bool
|
||||
"""
|
||||
@@ -287,10 +337,9 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
"""
|
||||
GPIO pin to monitor for state changes
|
||||
"""
|
||||
detection_triggered_high: builtins.bool
|
||||
detection_trigger_type: global___ModuleConfig.DetectionSensorConfig.TriggerType.ValueType
|
||||
"""
|
||||
Whether or not the GPIO pin state detection is triggered on HIGH (1)
|
||||
Otherwise LOW (0)
|
||||
The type of trigger event to be used
|
||||
"""
|
||||
use_pullup: builtins.bool
|
||||
"""
|
||||
@@ -306,10 +355,10 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
send_bell: builtins.bool = ...,
|
||||
name: builtins.str = ...,
|
||||
monitor_pin: builtins.int = ...,
|
||||
detection_triggered_high: builtins.bool = ...,
|
||||
detection_trigger_type: global___ModuleConfig.DetectionSensorConfig.TriggerType.ValueType = ...,
|
||||
use_pullup: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["detection_triggered_high", b"detection_triggered_high", "enabled", b"enabled", "minimum_broadcast_secs", b"minimum_broadcast_secs", "monitor_pin", b"monitor_pin", "name", b"name", "send_bell", b"send_bell", "state_broadcast_secs", b"state_broadcast_secs", "use_pullup", b"use_pullup"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["detection_trigger_type", b"detection_trigger_type", "enabled", b"enabled", "minimum_broadcast_secs", b"minimum_broadcast_secs", "monitor_pin", b"monitor_pin", "name", b"name", "send_bell", b"send_bell", "state_broadcast_secs", b"state_broadcast_secs", "use_pullup", b"use_pullup"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class AudioConfig(google.protobuf.message.Message):
|
||||
@@ -793,6 +842,9 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
POWER_MEASUREMENT_ENABLED_FIELD_NUMBER: builtins.int
|
||||
POWER_UPDATE_INTERVAL_FIELD_NUMBER: builtins.int
|
||||
POWER_SCREEN_ENABLED_FIELD_NUMBER: builtins.int
|
||||
HEALTH_MEASUREMENT_ENABLED_FIELD_NUMBER: builtins.int
|
||||
HEALTH_UPDATE_INTERVAL_FIELD_NUMBER: builtins.int
|
||||
HEALTH_SCREEN_ENABLED_FIELD_NUMBER: builtins.int
|
||||
device_update_interval: builtins.int
|
||||
"""
|
||||
Interval in seconds of how often we should try to send our
|
||||
@@ -828,18 +880,30 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
"""
|
||||
power_measurement_enabled: builtins.bool
|
||||
"""
|
||||
Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh
|
||||
Enable/disable Power metrics
|
||||
"""
|
||||
power_update_interval: builtins.int
|
||||
"""
|
||||
Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh
|
||||
power metrics to the mesh
|
||||
"""
|
||||
power_screen_enabled: builtins.bool
|
||||
"""
|
||||
Enable/Disable the power measurement module on-device display
|
||||
"""
|
||||
health_measurement_enabled: builtins.bool
|
||||
"""
|
||||
Preferences for the (Health) Telemetry Module
|
||||
Enable/Disable the telemetry measurement module measurement collection
|
||||
"""
|
||||
health_update_interval: builtins.int
|
||||
"""
|
||||
Interval in seconds of how often we should try to send our
|
||||
air quality metrics to the mesh
|
||||
health metrics to the mesh
|
||||
"""
|
||||
health_screen_enabled: builtins.bool
|
||||
"""
|
||||
Enable/Disable the health telemetry module on-device display
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
@@ -854,13 +918,16 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
power_measurement_enabled: builtins.bool = ...,
|
||||
power_update_interval: builtins.int = ...,
|
||||
power_screen_enabled: builtins.bool = ...,
|
||||
health_measurement_enabled: builtins.bool = ...,
|
||||
health_update_interval: builtins.int = ...,
|
||||
health_screen_enabled: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["air_quality_enabled", b"air_quality_enabled", "air_quality_interval", b"air_quality_interval", "device_update_interval", b"device_update_interval", "environment_display_fahrenheit", b"environment_display_fahrenheit", "environment_measurement_enabled", b"environment_measurement_enabled", "environment_screen_enabled", b"environment_screen_enabled", "environment_update_interval", b"environment_update_interval", "power_measurement_enabled", b"power_measurement_enabled", "power_screen_enabled", b"power_screen_enabled", "power_update_interval", b"power_update_interval"]) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["air_quality_enabled", b"air_quality_enabled", "air_quality_interval", b"air_quality_interval", "device_update_interval", b"device_update_interval", "environment_display_fahrenheit", b"environment_display_fahrenheit", "environment_measurement_enabled", b"environment_measurement_enabled", "environment_screen_enabled", b"environment_screen_enabled", "environment_update_interval", b"environment_update_interval", "health_measurement_enabled", b"health_measurement_enabled", "health_screen_enabled", b"health_screen_enabled", "health_update_interval", b"health_update_interval", "power_measurement_enabled", b"power_measurement_enabled", "power_screen_enabled", b"power_screen_enabled", "power_update_interval", b"power_update_interval"]) -> None: ...
|
||||
|
||||
@typing.final
|
||||
class CannedMessageConfig(google.protobuf.message.Message):
|
||||
"""
|
||||
TODO: REPLACE
|
||||
Canned Messages Module Config
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
@@ -992,7 +1059,7 @@ class ModuleConfig(google.protobuf.message.Message):
|
||||
allow_input_source: builtins.str
|
||||
"""
|
||||
Input event origin accepted by the canned message module.
|
||||
Can be e.g. "rotEnc1", "upDownEnc1" or keyword "_any"
|
||||
Can be e.g. "rotEnc1", "upDownEnc1", "scanAndSelect", "cardkb", "serialkb", or keyword "_any"
|
||||
"""
|
||||
send_bell: builtins.bool
|
||||
"""
|
||||
|
||||
4
meshtastic/protobuf/portnums_pb2.py
generated
4
meshtastic/protobuf/portnums_pb2.py
generated
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xa2\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xb1\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tALERT_APP\x10\x0b\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
@@ -22,5 +22,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
|
||||
_globals['_PORTNUM']._serialized_start=60
|
||||
_globals['_PORTNUM']._serialized_end=606
|
||||
_globals['_PORTNUM']._serialized_end=621
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
||||
12
meshtastic/protobuf/portnums_pb2.pyi
generated
12
meshtastic/protobuf/portnums_pb2.pyi
generated
@@ -93,6 +93,10 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy
|
||||
Same as Text Message but originating from Detection Sensor Module.
|
||||
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
|
||||
"""
|
||||
ALERT_APP: _PortNum.ValueType # 11
|
||||
"""
|
||||
Same as Text Message but used for critical alerts.
|
||||
"""
|
||||
REPLY_APP: _PortNum.ValueType # 32
|
||||
"""
|
||||
Provides a 'ping' service that replies to any packet it receives.
|
||||
@@ -154,7 +158,7 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy
|
||||
TRACEROUTE_APP: _PortNum.ValueType # 70
|
||||
"""
|
||||
Provides a traceroute functionality to show the route a packet towards
|
||||
a certain destination would take on the mesh.
|
||||
a certain destination would take on the mesh. Contains a RouteDiscovery message as payload.
|
||||
ENCODING: Protobuf
|
||||
"""
|
||||
NEIGHBORINFO_APP: _PortNum.ValueType # 71
|
||||
@@ -278,6 +282,10 @@ DETECTION_SENSOR_APP: PortNum.ValueType # 10
|
||||
Same as Text Message but originating from Detection Sensor Module.
|
||||
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9
|
||||
"""
|
||||
ALERT_APP: PortNum.ValueType # 11
|
||||
"""
|
||||
Same as Text Message but used for critical alerts.
|
||||
"""
|
||||
REPLY_APP: PortNum.ValueType # 32
|
||||
"""
|
||||
Provides a 'ping' service that replies to any packet it receives.
|
||||
@@ -339,7 +347,7 @@ ENCODING: Protobuf (?)
|
||||
TRACEROUTE_APP: PortNum.ValueType # 70
|
||||
"""
|
||||
Provides a traceroute functionality to show the route a packet towards
|
||||
a certain destination would take on the mesh.
|
||||
a certain destination would take on the mesh. Contains a RouteDiscovery message as payload.
|
||||
ENCODING: Protobuf
|
||||
"""
|
||||
NEIGHBORINFO_APP: PortNum.ValueType # 71
|
||||
|
||||
32
meshtastic/protobuf/telemetry_pb2.py
generated
32
meshtastic/protobuf/telemetry_pb2.py
generated
File diff suppressed because one or more lines are too long
407
meshtastic/protobuf/telemetry_pb2.pyi
generated
407
meshtastic/protobuf/telemetry_pb2.pyi
generated
@@ -139,6 +139,34 @@ class _TelemetrySensorTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wra
|
||||
"""
|
||||
MAX17048 1S lipo battery sensor (voltage, state of charge, time to go)
|
||||
"""
|
||||
CUSTOM_SENSOR: _TelemetrySensorType.ValueType # 29
|
||||
"""
|
||||
Custom I2C sensor implementation based on https://github.com/meshtastic/i2c-sensor
|
||||
"""
|
||||
MAX30102: _TelemetrySensorType.ValueType # 30
|
||||
"""
|
||||
MAX30102 Pulse Oximeter and Heart-Rate Sensor
|
||||
"""
|
||||
MLX90614: _TelemetrySensorType.ValueType # 31
|
||||
"""
|
||||
MLX90614 non-contact IR temperature sensor
|
||||
"""
|
||||
SCD4X: _TelemetrySensorType.ValueType # 32
|
||||
"""
|
||||
SCD40/SCD41 CO2, humidity, temperature sensor
|
||||
"""
|
||||
RADSENS: _TelemetrySensorType.ValueType # 33
|
||||
"""
|
||||
ClimateGuard RadSens, radiation, Geiger-Muller Tube
|
||||
"""
|
||||
INA226: _TelemetrySensorType.ValueType # 34
|
||||
"""
|
||||
High accuracy current and voltage
|
||||
"""
|
||||
DFROBOT_RAIN: _TelemetrySensorType.ValueType # 35
|
||||
"""
|
||||
DFRobot Gravity tipping bucket rain gauge
|
||||
"""
|
||||
|
||||
class TelemetrySensorType(_TelemetrySensorType, metaclass=_TelemetrySensorTypeEnumTypeWrapper):
|
||||
"""
|
||||
@@ -261,6 +289,34 @@ MAX17048: TelemetrySensorType.ValueType # 28
|
||||
"""
|
||||
MAX17048 1S lipo battery sensor (voltage, state of charge, time to go)
|
||||
"""
|
||||
CUSTOM_SENSOR: TelemetrySensorType.ValueType # 29
|
||||
"""
|
||||
Custom I2C sensor implementation based on https://github.com/meshtastic/i2c-sensor
|
||||
"""
|
||||
MAX30102: TelemetrySensorType.ValueType # 30
|
||||
"""
|
||||
MAX30102 Pulse Oximeter and Heart-Rate Sensor
|
||||
"""
|
||||
MLX90614: TelemetrySensorType.ValueType # 31
|
||||
"""
|
||||
MLX90614 non-contact IR temperature sensor
|
||||
"""
|
||||
SCD4X: TelemetrySensorType.ValueType # 32
|
||||
"""
|
||||
SCD40/SCD41 CO2, humidity, temperature sensor
|
||||
"""
|
||||
RADSENS: TelemetrySensorType.ValueType # 33
|
||||
"""
|
||||
ClimateGuard RadSens, radiation, Geiger-Muller Tube
|
||||
"""
|
||||
INA226: TelemetrySensorType.ValueType # 34
|
||||
"""
|
||||
High accuracy current and voltage
|
||||
"""
|
||||
DFROBOT_RAIN: TelemetrySensorType.ValueType # 35
|
||||
"""
|
||||
DFRobot Gravity tipping bucket rain gauge
|
||||
"""
|
||||
global___TelemetrySensorType = TelemetrySensorType
|
||||
|
||||
@typing.final
|
||||
@@ -299,13 +355,24 @@ class DeviceMetrics(google.protobuf.message.Message):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
battery_level: builtins.int = ...,
|
||||
voltage: builtins.float = ...,
|
||||
channel_utilization: builtins.float = ...,
|
||||
air_util_tx: builtins.float = ...,
|
||||
uptime_seconds: builtins.int = ...,
|
||||
battery_level: builtins.int | None = ...,
|
||||
voltage: builtins.float | None = ...,
|
||||
channel_utilization: builtins.float | None = ...,
|
||||
air_util_tx: builtins.float | None = ...,
|
||||
uptime_seconds: builtins.int | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["air_util_tx", b"air_util_tx", "battery_level", b"battery_level", "channel_utilization", b"channel_utilization", "uptime_seconds", b"uptime_seconds", "voltage", b"voltage"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_air_util_tx", b"_air_util_tx", "_battery_level", b"_battery_level", "_channel_utilization", b"_channel_utilization", "_uptime_seconds", b"_uptime_seconds", "_voltage", b"_voltage", "air_util_tx", b"air_util_tx", "battery_level", b"battery_level", "channel_utilization", b"channel_utilization", "uptime_seconds", b"uptime_seconds", "voltage", b"voltage"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_air_util_tx", b"_air_util_tx", "_battery_level", b"_battery_level", "_channel_utilization", b"_channel_utilization", "_uptime_seconds", b"_uptime_seconds", "_voltage", b"_voltage", "air_util_tx", b"air_util_tx", "battery_level", b"battery_level", "channel_utilization", b"channel_utilization", "uptime_seconds", b"uptime_seconds", "voltage", b"voltage"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_air_util_tx", b"_air_util_tx"]) -> typing.Literal["air_util_tx"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_battery_level", b"_battery_level"]) -> typing.Literal["battery_level"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_channel_utilization", b"_channel_utilization"]) -> typing.Literal["channel_utilization"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_uptime_seconds", b"_uptime_seconds"]) -> typing.Literal["uptime_seconds"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_voltage", b"_voltage"]) -> typing.Literal["voltage"] | None: ...
|
||||
|
||||
global___DeviceMetrics = DeviceMetrics
|
||||
|
||||
@@ -334,6 +401,9 @@ class EnvironmentMetrics(google.protobuf.message.Message):
|
||||
WEIGHT_FIELD_NUMBER: builtins.int
|
||||
WIND_GUST_FIELD_NUMBER: builtins.int
|
||||
WIND_LULL_FIELD_NUMBER: builtins.int
|
||||
RADIATION_FIELD_NUMBER: builtins.int
|
||||
RAINFALL_1H_FIELD_NUMBER: builtins.int
|
||||
RAINFALL_24H_FIELD_NUMBER: builtins.int
|
||||
temperature: builtins.float
|
||||
"""
|
||||
Temperature measured
|
||||
@@ -404,28 +474,84 @@ class EnvironmentMetrics(google.protobuf.message.Message):
|
||||
"""
|
||||
Wind lull in m/s
|
||||
"""
|
||||
radiation: builtins.float
|
||||
"""
|
||||
Radiation in µR/h
|
||||
"""
|
||||
rainfall_1h: builtins.float
|
||||
"""
|
||||
Rainfall in the last hour in mm
|
||||
"""
|
||||
rainfall_24h: builtins.float
|
||||
"""
|
||||
Rainfall in the last 24 hours in mm
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
temperature: builtins.float = ...,
|
||||
relative_humidity: builtins.float = ...,
|
||||
barometric_pressure: builtins.float = ...,
|
||||
gas_resistance: builtins.float = ...,
|
||||
voltage: builtins.float = ...,
|
||||
current: builtins.float = ...,
|
||||
iaq: builtins.int = ...,
|
||||
distance: builtins.float = ...,
|
||||
lux: builtins.float = ...,
|
||||
white_lux: builtins.float = ...,
|
||||
ir_lux: builtins.float = ...,
|
||||
uv_lux: builtins.float = ...,
|
||||
wind_direction: builtins.int = ...,
|
||||
wind_speed: builtins.float = ...,
|
||||
weight: builtins.float = ...,
|
||||
wind_gust: builtins.float = ...,
|
||||
wind_lull: builtins.float = ...,
|
||||
temperature: builtins.float | None = ...,
|
||||
relative_humidity: builtins.float | None = ...,
|
||||
barometric_pressure: builtins.float | None = ...,
|
||||
gas_resistance: builtins.float | None = ...,
|
||||
voltage: builtins.float | None = ...,
|
||||
current: builtins.float | None = ...,
|
||||
iaq: builtins.int | None = ...,
|
||||
distance: builtins.float | None = ...,
|
||||
lux: builtins.float | None = ...,
|
||||
white_lux: builtins.float | None = ...,
|
||||
ir_lux: builtins.float | None = ...,
|
||||
uv_lux: builtins.float | None = ...,
|
||||
wind_direction: builtins.int | None = ...,
|
||||
wind_speed: builtins.float | None = ...,
|
||||
weight: builtins.float | None = ...,
|
||||
wind_gust: builtins.float | None = ...,
|
||||
wind_lull: builtins.float | None = ...,
|
||||
radiation: builtins.float | None = ...,
|
||||
rainfall_1h: builtins.float | None = ...,
|
||||
rainfall_24h: builtins.float | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "relative_humidity", b"relative_humidity", "temperature", b"temperature", "uv_lux", b"uv_lux", "voltage", b"voltage", "weight", b"weight", "white_lux", b"white_lux", "wind_direction", b"wind_direction", "wind_gust", b"wind_gust", "wind_lull", b"wind_lull", "wind_speed", b"wind_speed"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_barometric_pressure", b"_barometric_pressure", "_current", b"_current", "_distance", b"_distance", "_gas_resistance", b"_gas_resistance", "_iaq", b"_iaq", "_ir_lux", b"_ir_lux", "_lux", b"_lux", "_radiation", b"_radiation", "_rainfall_1h", b"_rainfall_1h", "_rainfall_24h", b"_rainfall_24h", "_relative_humidity", b"_relative_humidity", "_temperature", b"_temperature", "_uv_lux", b"_uv_lux", "_voltage", b"_voltage", "_weight", b"_weight", "_white_lux", b"_white_lux", "_wind_direction", b"_wind_direction", "_wind_gust", b"_wind_gust", "_wind_lull", b"_wind_lull", "_wind_speed", b"_wind_speed", "barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "radiation", b"radiation", "rainfall_1h", b"rainfall_1h", "rainfall_24h", b"rainfall_24h", "relative_humidity", b"relative_humidity", "temperature", b"temperature", "uv_lux", b"uv_lux", "voltage", b"voltage", "weight", b"weight", "white_lux", b"white_lux", "wind_direction", b"wind_direction", "wind_gust", b"wind_gust", "wind_lull", b"wind_lull", "wind_speed", b"wind_speed"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_barometric_pressure", b"_barometric_pressure", "_current", b"_current", "_distance", b"_distance", "_gas_resistance", b"_gas_resistance", "_iaq", b"_iaq", "_ir_lux", b"_ir_lux", "_lux", b"_lux", "_radiation", b"_radiation", "_rainfall_1h", b"_rainfall_1h", "_rainfall_24h", b"_rainfall_24h", "_relative_humidity", b"_relative_humidity", "_temperature", b"_temperature", "_uv_lux", b"_uv_lux", "_voltage", b"_voltage", "_weight", b"_weight", "_white_lux", b"_white_lux", "_wind_direction", b"_wind_direction", "_wind_gust", b"_wind_gust", "_wind_lull", b"_wind_lull", "_wind_speed", b"_wind_speed", "barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "radiation", b"radiation", "rainfall_1h", b"rainfall_1h", "rainfall_24h", b"rainfall_24h", "relative_humidity", b"relative_humidity", "temperature", b"temperature", "uv_lux", b"uv_lux", "voltage", b"voltage", "weight", b"weight", "white_lux", b"white_lux", "wind_direction", b"wind_direction", "wind_gust", b"wind_gust", "wind_lull", b"wind_lull", "wind_speed", b"wind_speed"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_barometric_pressure", b"_barometric_pressure"]) -> typing.Literal["barometric_pressure"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_current", b"_current"]) -> typing.Literal["current"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_distance", b"_distance"]) -> typing.Literal["distance"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_gas_resistance", b"_gas_resistance"]) -> typing.Literal["gas_resistance"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_iaq", b"_iaq"]) -> typing.Literal["iaq"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ir_lux", b"_ir_lux"]) -> typing.Literal["ir_lux"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_lux", b"_lux"]) -> typing.Literal["lux"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_radiation", b"_radiation"]) -> typing.Literal["radiation"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_rainfall_1h", b"_rainfall_1h"]) -> typing.Literal["rainfall_1h"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_rainfall_24h", b"_rainfall_24h"]) -> typing.Literal["rainfall_24h"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_relative_humidity", b"_relative_humidity"]) -> typing.Literal["relative_humidity"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_temperature", b"_temperature"]) -> typing.Literal["temperature"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_uv_lux", b"_uv_lux"]) -> typing.Literal["uv_lux"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_voltage", b"_voltage"]) -> typing.Literal["voltage"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_weight", b"_weight"]) -> typing.Literal["weight"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_white_lux", b"_white_lux"]) -> typing.Literal["white_lux"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_wind_direction", b"_wind_direction"]) -> typing.Literal["wind_direction"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_wind_gust", b"_wind_gust"]) -> typing.Literal["wind_gust"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_wind_lull", b"_wind_lull"]) -> typing.Literal["wind_lull"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_wind_speed", b"_wind_speed"]) -> typing.Literal["wind_speed"] | None: ...
|
||||
|
||||
global___EnvironmentMetrics = EnvironmentMetrics
|
||||
|
||||
@@ -470,14 +596,27 @@ class PowerMetrics(google.protobuf.message.Message):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
ch1_voltage: builtins.float = ...,
|
||||
ch1_current: builtins.float = ...,
|
||||
ch2_voltage: builtins.float = ...,
|
||||
ch2_current: builtins.float = ...,
|
||||
ch3_voltage: builtins.float = ...,
|
||||
ch3_current: builtins.float = ...,
|
||||
ch1_voltage: builtins.float | None = ...,
|
||||
ch1_current: builtins.float | None = ...,
|
||||
ch2_voltage: builtins.float | None = ...,
|
||||
ch2_current: builtins.float | None = ...,
|
||||
ch3_voltage: builtins.float | None = ...,
|
||||
ch3_current: builtins.float | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["ch1_current", b"ch1_current", "ch1_voltage", b"ch1_voltage", "ch2_current", b"ch2_current", "ch2_voltage", b"ch2_voltage", "ch3_current", b"ch3_current", "ch3_voltage", b"ch3_voltage"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_ch1_current", b"_ch1_current", "_ch1_voltage", b"_ch1_voltage", "_ch2_current", b"_ch2_current", "_ch2_voltage", b"_ch2_voltage", "_ch3_current", b"_ch3_current", "_ch3_voltage", b"_ch3_voltage", "ch1_current", b"ch1_current", "ch1_voltage", b"ch1_voltage", "ch2_current", b"ch2_current", "ch2_voltage", b"ch2_voltage", "ch3_current", b"ch3_current", "ch3_voltage", b"ch3_voltage"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_ch1_current", b"_ch1_current", "_ch1_voltage", b"_ch1_voltage", "_ch2_current", b"_ch2_current", "_ch2_voltage", b"_ch2_voltage", "_ch3_current", b"_ch3_current", "_ch3_voltage", b"_ch3_voltage", "ch1_current", b"ch1_current", "ch1_voltage", b"ch1_voltage", "ch2_current", b"ch2_current", "ch2_voltage", b"ch2_voltage", "ch3_current", b"ch3_current", "ch3_voltage", b"ch3_voltage"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ch1_current", b"_ch1_current"]) -> typing.Literal["ch1_current"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ch1_voltage", b"_ch1_voltage"]) -> typing.Literal["ch1_voltage"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ch2_current", b"_ch2_current"]) -> typing.Literal["ch2_current"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ch2_voltage", b"_ch2_voltage"]) -> typing.Literal["ch2_voltage"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ch3_current", b"_ch3_current"]) -> typing.Literal["ch3_current"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_ch3_voltage", b"_ch3_voltage"]) -> typing.Literal["ch3_voltage"] | None: ...
|
||||
|
||||
global___PowerMetrics = PowerMetrics
|
||||
|
||||
@@ -501,6 +640,7 @@ class AirQualityMetrics(google.protobuf.message.Message):
|
||||
PARTICLES_25UM_FIELD_NUMBER: builtins.int
|
||||
PARTICLES_50UM_FIELD_NUMBER: builtins.int
|
||||
PARTICLES_100UM_FIELD_NUMBER: builtins.int
|
||||
CO2_FIELD_NUMBER: builtins.int
|
||||
pm10_standard: builtins.int
|
||||
"""
|
||||
Concentration Units Standard PM1.0
|
||||
@@ -549,26 +689,183 @@ class AirQualityMetrics(google.protobuf.message.Message):
|
||||
"""
|
||||
10.0um Particle Count
|
||||
"""
|
||||
co2: builtins.int
|
||||
"""
|
||||
10.0um Particle Count
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
pm10_standard: builtins.int = ...,
|
||||
pm25_standard: builtins.int = ...,
|
||||
pm100_standard: builtins.int = ...,
|
||||
pm10_environmental: builtins.int = ...,
|
||||
pm25_environmental: builtins.int = ...,
|
||||
pm100_environmental: builtins.int = ...,
|
||||
particles_03um: builtins.int = ...,
|
||||
particles_05um: builtins.int = ...,
|
||||
particles_10um: builtins.int = ...,
|
||||
particles_25um: builtins.int = ...,
|
||||
particles_50um: builtins.int = ...,
|
||||
particles_100um: builtins.int = ...,
|
||||
pm10_standard: builtins.int | None = ...,
|
||||
pm25_standard: builtins.int | None = ...,
|
||||
pm100_standard: builtins.int | None = ...,
|
||||
pm10_environmental: builtins.int | None = ...,
|
||||
pm25_environmental: builtins.int | None = ...,
|
||||
pm100_environmental: builtins.int | None = ...,
|
||||
particles_03um: builtins.int | None = ...,
|
||||
particles_05um: builtins.int | None = ...,
|
||||
particles_10um: builtins.int | None = ...,
|
||||
particles_25um: builtins.int | None = ...,
|
||||
particles_50um: builtins.int | None = ...,
|
||||
particles_100um: builtins.int | None = ...,
|
||||
co2: builtins.int | None = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["particles_03um", b"particles_03um", "particles_05um", b"particles_05um", "particles_100um", b"particles_100um", "particles_10um", b"particles_10um", "particles_25um", b"particles_25um", "particles_50um", b"particles_50um", "pm100_environmental", b"pm100_environmental", "pm100_standard", b"pm100_standard", "pm10_environmental", b"pm10_environmental", "pm10_standard", b"pm10_standard", "pm25_environmental", b"pm25_environmental", "pm25_standard", b"pm25_standard"]) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_co2", b"_co2", "_particles_03um", b"_particles_03um", "_particles_05um", b"_particles_05um", "_particles_100um", b"_particles_100um", "_particles_10um", b"_particles_10um", "_particles_25um", b"_particles_25um", "_particles_50um", b"_particles_50um", "_pm100_environmental", b"_pm100_environmental", "_pm100_standard", b"_pm100_standard", "_pm10_environmental", b"_pm10_environmental", "_pm10_standard", b"_pm10_standard", "_pm25_environmental", b"_pm25_environmental", "_pm25_standard", b"_pm25_standard", "co2", b"co2", "particles_03um", b"particles_03um", "particles_05um", b"particles_05um", "particles_100um", b"particles_100um", "particles_10um", b"particles_10um", "particles_25um", b"particles_25um", "particles_50um", b"particles_50um", "pm100_environmental", b"pm100_environmental", "pm100_standard", b"pm100_standard", "pm10_environmental", b"pm10_environmental", "pm10_standard", b"pm10_standard", "pm25_environmental", b"pm25_environmental", "pm25_standard", b"pm25_standard"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_co2", b"_co2", "_particles_03um", b"_particles_03um", "_particles_05um", b"_particles_05um", "_particles_100um", b"_particles_100um", "_particles_10um", b"_particles_10um", "_particles_25um", b"_particles_25um", "_particles_50um", b"_particles_50um", "_pm100_environmental", b"_pm100_environmental", "_pm100_standard", b"_pm100_standard", "_pm10_environmental", b"_pm10_environmental", "_pm10_standard", b"_pm10_standard", "_pm25_environmental", b"_pm25_environmental", "_pm25_standard", b"_pm25_standard", "co2", b"co2", "particles_03um", b"particles_03um", "particles_05um", b"particles_05um", "particles_100um", b"particles_100um", "particles_10um", b"particles_10um", "particles_25um", b"particles_25um", "particles_50um", b"particles_50um", "pm100_environmental", b"pm100_environmental", "pm100_standard", b"pm100_standard", "pm10_environmental", b"pm10_environmental", "pm10_standard", b"pm10_standard", "pm25_environmental", b"pm25_environmental", "pm25_standard", b"pm25_standard"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_co2", b"_co2"]) -> typing.Literal["co2"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_particles_03um", b"_particles_03um"]) -> typing.Literal["particles_03um"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_particles_05um", b"_particles_05um"]) -> typing.Literal["particles_05um"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_particles_100um", b"_particles_100um"]) -> typing.Literal["particles_100um"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_particles_10um", b"_particles_10um"]) -> typing.Literal["particles_10um"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_particles_25um", b"_particles_25um"]) -> typing.Literal["particles_25um"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_particles_50um", b"_particles_50um"]) -> typing.Literal["particles_50um"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_pm100_environmental", b"_pm100_environmental"]) -> typing.Literal["pm100_environmental"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_pm100_standard", b"_pm100_standard"]) -> typing.Literal["pm100_standard"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_pm10_environmental", b"_pm10_environmental"]) -> typing.Literal["pm10_environmental"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_pm10_standard", b"_pm10_standard"]) -> typing.Literal["pm10_standard"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_pm25_environmental", b"_pm25_environmental"]) -> typing.Literal["pm25_environmental"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_pm25_standard", b"_pm25_standard"]) -> typing.Literal["pm25_standard"] | None: ...
|
||||
|
||||
global___AirQualityMetrics = AirQualityMetrics
|
||||
|
||||
@typing.final
|
||||
class LocalStats(google.protobuf.message.Message):
|
||||
"""
|
||||
Local device mesh statistics
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
UPTIME_SECONDS_FIELD_NUMBER: builtins.int
|
||||
CHANNEL_UTILIZATION_FIELD_NUMBER: builtins.int
|
||||
AIR_UTIL_TX_FIELD_NUMBER: builtins.int
|
||||
NUM_PACKETS_TX_FIELD_NUMBER: builtins.int
|
||||
NUM_PACKETS_RX_FIELD_NUMBER: builtins.int
|
||||
NUM_PACKETS_RX_BAD_FIELD_NUMBER: builtins.int
|
||||
NUM_ONLINE_NODES_FIELD_NUMBER: builtins.int
|
||||
NUM_TOTAL_NODES_FIELD_NUMBER: builtins.int
|
||||
NUM_RX_DUPE_FIELD_NUMBER: builtins.int
|
||||
NUM_TX_RELAY_FIELD_NUMBER: builtins.int
|
||||
NUM_TX_RELAY_CANCELED_FIELD_NUMBER: builtins.int
|
||||
uptime_seconds: builtins.int
|
||||
"""
|
||||
How long the device has been running since the last reboot (in seconds)
|
||||
"""
|
||||
channel_utilization: builtins.float
|
||||
"""
|
||||
Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise).
|
||||
"""
|
||||
air_util_tx: builtins.float
|
||||
"""
|
||||
Percent of airtime for transmission used within the last hour.
|
||||
"""
|
||||
num_packets_tx: builtins.int
|
||||
"""
|
||||
Number of packets sent
|
||||
"""
|
||||
num_packets_rx: builtins.int
|
||||
"""
|
||||
Number of packets received (both good and bad)
|
||||
"""
|
||||
num_packets_rx_bad: builtins.int
|
||||
"""
|
||||
Number of packets received that are malformed or violate the protocol
|
||||
"""
|
||||
num_online_nodes: builtins.int
|
||||
"""
|
||||
Number of nodes online (in the past 2 hours)
|
||||
"""
|
||||
num_total_nodes: builtins.int
|
||||
"""
|
||||
Number of nodes total
|
||||
"""
|
||||
num_rx_dupe: builtins.int
|
||||
"""
|
||||
Number of received packets that were duplicates (due to multiple nodes relaying).
|
||||
If this number is high, there are nodes in the mesh relaying packets when it's unnecessary, for example due to the ROUTER/REPEATER role.
|
||||
"""
|
||||
num_tx_relay: builtins.int
|
||||
"""
|
||||
Number of packets we transmitted that were a relay for others (not originating from ourselves).
|
||||
"""
|
||||
num_tx_relay_canceled: builtins.int
|
||||
"""
|
||||
Number of times we canceled a packet to be relayed, because someone else did it before us.
|
||||
This will always be zero for ROUTERs/REPEATERs. If this number is high, some other node(s) is/are relaying faster than you.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
uptime_seconds: builtins.int = ...,
|
||||
channel_utilization: builtins.float = ...,
|
||||
air_util_tx: builtins.float = ...,
|
||||
num_packets_tx: builtins.int = ...,
|
||||
num_packets_rx: builtins.int = ...,
|
||||
num_packets_rx_bad: builtins.int = ...,
|
||||
num_online_nodes: builtins.int = ...,
|
||||
num_total_nodes: builtins.int = ...,
|
||||
num_rx_dupe: builtins.int = ...,
|
||||
num_tx_relay: builtins.int = ...,
|
||||
num_tx_relay_canceled: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing.Literal["air_util_tx", b"air_util_tx", "channel_utilization", b"channel_utilization", "num_online_nodes", b"num_online_nodes", "num_packets_rx", b"num_packets_rx", "num_packets_rx_bad", b"num_packets_rx_bad", "num_packets_tx", b"num_packets_tx", "num_rx_dupe", b"num_rx_dupe", "num_total_nodes", b"num_total_nodes", "num_tx_relay", b"num_tx_relay", "num_tx_relay_canceled", b"num_tx_relay_canceled", "uptime_seconds", b"uptime_seconds"]) -> None: ...
|
||||
|
||||
global___LocalStats = LocalStats
|
||||
|
||||
@typing.final
|
||||
class HealthMetrics(google.protobuf.message.Message):
|
||||
"""
|
||||
Health telemetry metrics
|
||||
"""
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
|
||||
HEART_BPM_FIELD_NUMBER: builtins.int
|
||||
SPO2_FIELD_NUMBER: builtins.int
|
||||
TEMPERATURE_FIELD_NUMBER: builtins.int
|
||||
heart_bpm: builtins.int
|
||||
"""
|
||||
Heart rate (beats per minute)
|
||||
"""
|
||||
spO2: builtins.int
|
||||
"""
|
||||
SpO2 (blood oxygen saturation) level
|
||||
"""
|
||||
temperature: builtins.float
|
||||
"""
|
||||
Body temperature in degrees Celsius
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
heart_bpm: builtins.int | None = ...,
|
||||
spO2: builtins.int | None = ...,
|
||||
temperature: builtins.float | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["_heart_bpm", b"_heart_bpm", "_spO2", b"_spO2", "_temperature", b"_temperature", "heart_bpm", b"heart_bpm", "spO2", b"spO2", "temperature", b"temperature"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["_heart_bpm", b"_heart_bpm", "_spO2", b"_spO2", "_temperature", b"_temperature", "heart_bpm", b"heart_bpm", "spO2", b"spO2", "temperature", b"temperature"]) -> None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_heart_bpm", b"_heart_bpm"]) -> typing.Literal["heart_bpm"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_spO2", b"_spO2"]) -> typing.Literal["spO2"] | None: ...
|
||||
@typing.overload
|
||||
def WhichOneof(self, oneof_group: typing.Literal["_temperature", b"_temperature"]) -> typing.Literal["temperature"] | None: ...
|
||||
|
||||
global___HealthMetrics = HealthMetrics
|
||||
|
||||
@typing.final
|
||||
class Telemetry(google.protobuf.message.Message):
|
||||
"""
|
||||
@@ -582,6 +879,8 @@ class Telemetry(google.protobuf.message.Message):
|
||||
ENVIRONMENT_METRICS_FIELD_NUMBER: builtins.int
|
||||
AIR_QUALITY_METRICS_FIELD_NUMBER: builtins.int
|
||||
POWER_METRICS_FIELD_NUMBER: builtins.int
|
||||
LOCAL_STATS_FIELD_NUMBER: builtins.int
|
||||
HEALTH_METRICS_FIELD_NUMBER: builtins.int
|
||||
time: builtins.int
|
||||
"""
|
||||
Seconds since 1970 - or 0 for unknown/unset
|
||||
@@ -610,6 +909,18 @@ class Telemetry(google.protobuf.message.Message):
|
||||
Power Metrics
|
||||
"""
|
||||
|
||||
@property
|
||||
def local_stats(self) -> global___LocalStats:
|
||||
"""
|
||||
Local device mesh statistics
|
||||
"""
|
||||
|
||||
@property
|
||||
def health_metrics(self) -> global___HealthMetrics:
|
||||
"""
|
||||
Health telemetry metrics
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
@@ -618,10 +929,12 @@ class Telemetry(google.protobuf.message.Message):
|
||||
environment_metrics: global___EnvironmentMetrics | None = ...,
|
||||
air_quality_metrics: global___AirQualityMetrics | None = ...,
|
||||
power_metrics: global___PowerMetrics | None = ...,
|
||||
local_stats: global___LocalStats | None = ...,
|
||||
health_metrics: global___HealthMetrics | None = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "power_metrics", b"power_metrics", "variant", b"variant"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "power_metrics", b"power_metrics", "time", b"time", "variant", b"variant"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["variant", b"variant"]) -> typing.Literal["device_metrics", "environment_metrics", "air_quality_metrics", "power_metrics"] | None: ...
|
||||
def HasField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "health_metrics", b"health_metrics", "local_stats", b"local_stats", "power_metrics", b"power_metrics", "variant", b"variant"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "health_metrics", b"health_metrics", "local_stats", b"local_stats", "power_metrics", b"power_metrics", "time", b"time", "variant", b"variant"]) -> None: ...
|
||||
def WhichOneof(self, oneof_group: typing.Literal["variant", b"variant"]) -> typing.Literal["device_metrics", "environment_metrics", "air_quality_metrics", "power_metrics", "local_stats", "health_metrics"] | None: ...
|
||||
|
||||
global___Telemetry = Telemetry
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from meshtastic.protobuf import portnums_pb2, remote_hardware_pb2
|
||||
from meshtastic.util import our_exit
|
||||
|
||||
|
||||
def onGPIOreceive(packet, interface):
|
||||
def onGPIOreceive(packet, interface) -> None:
|
||||
"""Callback for received GPIO responses"""
|
||||
logging.debug(f"packet:{packet} interface:{interface}")
|
||||
gpioValue = 0
|
||||
@@ -37,7 +37,7 @@ class RemoteHardwareClient:
|
||||
code for how you can connect to your own custom meshtastic services
|
||||
"""
|
||||
|
||||
def __init__(self, iface):
|
||||
def __init__(self, iface) -> None:
|
||||
"""
|
||||
Constructor
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
""" Serial interface class
|
||||
"""
|
||||
# pylint: disable=R0917
|
||||
import logging
|
||||
import platform
|
||||
import time
|
||||
|
||||
from typing import Optional
|
||||
from typing import List, Optional
|
||||
|
||||
import serial # type: ignore[import-untyped]
|
||||
|
||||
@@ -18,7 +19,7 @@ if platform.system() != "Windows":
|
||||
class SerialInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a serial link"""
|
||||
|
||||
def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto=False, connectNow=True, noNodes: bool=False):
|
||||
def __init__(self, devPath: Optional[str]=None, debugOut=None, noProto: bool=False, connectNow: bool=True, noNodes: bool=False) -> None:
|
||||
"""Constructor, opens a connection to a specified serial port, or if unspecified try to
|
||||
find one Meshtastic device by probing
|
||||
|
||||
@@ -31,13 +32,13 @@ class SerialInterface(StreamInterface):
|
||||
self.devPath: Optional[str] = devPath
|
||||
|
||||
if self.devPath is None:
|
||||
ports = meshtastic.util.findPorts(True)
|
||||
ports: List[str] = meshtastic.util.findPorts(True)
|
||||
logging.debug(f"ports:{ports}")
|
||||
if len(ports) == 0:
|
||||
print("No Serial Meshtastic device detected, attempting TCP connection on localhost.")
|
||||
return
|
||||
elif len(ports) > 1:
|
||||
message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
|
||||
message: str = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
|
||||
message += f" Ports detected:{ports}"
|
||||
meshtastic.util.our_exit(message)
|
||||
else:
|
||||
@@ -58,14 +59,14 @@ class SerialInterface(StreamInterface):
|
||||
self.stream = serial.Serial(
|
||||
self.devPath, 115200, exclusive=True, timeout=0.5, write_timeout=0
|
||||
)
|
||||
self.stream.flush()
|
||||
self.stream.flush() # type: ignore[attr-defined]
|
||||
time.sleep(0.1)
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes
|
||||
)
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
"""Close a connection to the device"""
|
||||
if self.stream: # Stream can be null if we were already closed
|
||||
self.stream.flush() # FIXME: why are there these two flushes with 100ms sleeps? This shouldn't be necessary
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
"""Stream Interface base class
|
||||
"""
|
||||
import io
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from typing import Optional, cast
|
||||
|
||||
import serial # type: ignore[import-untyped]
|
||||
|
||||
from meshtastic.mesh_interface import MeshInterface
|
||||
@@ -19,7 +22,7 @@ MAX_TO_FROM_RADIO_SIZE = 512
|
||||
class StreamInterface(MeshInterface):
|
||||
"""Interface class for meshtastic devices over a stream link (serial, TCP, etc)"""
|
||||
|
||||
def __init__(self, debugOut=None, noProto=False, connectNow=True, noNodes=False):
|
||||
def __init__(self, debugOut: Optional[io.TextIOWrapper]=None, noProto: bool=False, connectNow: bool=True, noNodes: bool=False) -> None:
|
||||
"""Constructor, opens a connection to self.stream
|
||||
|
||||
Keyword Arguments:
|
||||
@@ -35,6 +38,7 @@ class StreamInterface(MeshInterface):
|
||||
raise Exception( # pylint: disable=W0719
|
||||
"StreamInterface is now abstract (to update existing code create SerialInterface instead)"
|
||||
)
|
||||
self.stream: Optional[serial.Serial] # only serial uses this, TCPInterface overrides the relevant methods instead
|
||||
self._rxBuf = bytes() # empty
|
||||
self._wantExit = False
|
||||
|
||||
@@ -52,7 +56,7 @@ class StreamInterface(MeshInterface):
|
||||
if not noProto:
|
||||
self.waitForConfig()
|
||||
|
||||
def connect(self):
|
||||
def connect(self) -> None:
|
||||
"""Connect to our radio
|
||||
|
||||
Normally this is called automatically by the constructor, but if you
|
||||
@@ -63,7 +67,7 @@ class StreamInterface(MeshInterface):
|
||||
# if the reading statemachine was parsing a bad packet make sure
|
||||
# we write enough start bytes to force it to resync (we don't use START1
|
||||
# because we want to ensure it is looking for START1)
|
||||
p = bytearray([START2] * 32)
|
||||
p: bytes = bytearray([START2] * 32)
|
||||
self._writeBytes(p)
|
||||
time.sleep(0.1) # wait 100ms to give device time to start running
|
||||
|
||||
@@ -74,7 +78,7 @@ class StreamInterface(MeshInterface):
|
||||
if not self.noProto: # Wait for the db download if using the protocol
|
||||
self._waitConnected()
|
||||
|
||||
def _disconnected(self):
|
||||
def _disconnected(self) -> None:
|
||||
"""We override the superclass implementation to close our port"""
|
||||
MeshInterface._disconnected(self)
|
||||
|
||||
@@ -86,7 +90,7 @@ class StreamInterface(MeshInterface):
|
||||
# pylint: disable=W0201
|
||||
self.stream = None
|
||||
|
||||
def _writeBytes(self, b):
|
||||
def _writeBytes(self, b: bytes) -> None:
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
if self.stream: # ignore writes when stream is closed
|
||||
self.stream.write(b)
|
||||
@@ -98,24 +102,24 @@ class StreamInterface(MeshInterface):
|
||||
# we sleep here to give the TBeam a chance to work
|
||||
time.sleep(0.1)
|
||||
|
||||
def _readBytes(self, length):
|
||||
def _readBytes(self, length) -> Optional[bytes]:
|
||||
"""Read an array of bytes from our stream"""
|
||||
if self.stream:
|
||||
return self.stream.read(length)
|
||||
else:
|
||||
return None
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
def _sendToRadioImpl(self, toRadio) -> None:
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
logging.debug(f"Sending: {stripnl(toRadio)}")
|
||||
b = toRadio.SerializeToString()
|
||||
bufLen = len(b)
|
||||
b: bytes = toRadio.SerializeToString()
|
||||
bufLen: int = 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])
|
||||
logging.debug(f"sending header:{header} b:{b}")
|
||||
header: bytes = bytes([START1, START2, (bufLen >> 8) & 0xFF, bufLen & 0xFF])
|
||||
logging.debug(f"sending header:{header!r} b:{b!r}")
|
||||
self._writeBytes(header + b)
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
"""Close a connection to the device"""
|
||||
logging.debug("Closing stream")
|
||||
MeshInterface.close(self)
|
||||
@@ -142,7 +146,7 @@ class StreamInterface(MeshInterface):
|
||||
else:
|
||||
self.cur_log_line += utf
|
||||
|
||||
def __reader(self):
|
||||
def __reader(self) -> None:
|
||||
"""The reader thread that reads bytes from our stream"""
|
||||
logging.debug("in __reader()")
|
||||
empty = bytes()
|
||||
@@ -150,13 +154,13 @@ class StreamInterface(MeshInterface):
|
||||
try:
|
||||
while not self._wantExit:
|
||||
# logging.debug("reading character")
|
||||
b = self._readBytes(1)
|
||||
b: Optional[bytes] = self._readBytes(1)
|
||||
# logging.debug("In reader loop")
|
||||
# logging.debug(f"read returned {b}")
|
||||
if len(b) > 0:
|
||||
c = b[0]
|
||||
if b is not None and len(cast(bytes, b)) > 0:
|
||||
c: int = b[0]
|
||||
# logging.debug(f'c:{c}')
|
||||
ptr = len(self._rxBuf)
|
||||
ptr: int = len(self._rxBuf)
|
||||
|
||||
# Assume we want to append this byte, fixme use bytearray instead
|
||||
self._rxBuf = self._rxBuf + b
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
""" Supported Meshtastic Devices - This is a class and collection of Meshtastic devices.
|
||||
It is used for auto detection as to which device might be connected.
|
||||
"""
|
||||
# pylint: disable=R0917
|
||||
|
||||
# Goal is to detect which device and port to use from the supported devices
|
||||
# without installing any libraries that are not currently in the python meshtastic library
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
"""TCPInterface class for interfacing with http endpoint
|
||||
"""
|
||||
# pylint: disable=R0917
|
||||
import logging
|
||||
import socket
|
||||
from typing import Optional
|
||||
from typing import Optional, cast
|
||||
|
||||
from meshtastic.stream_interface import StreamInterface
|
||||
|
||||
DEFAULT_TCP_PORT = 4403
|
||||
|
||||
class TCPInterface(StreamInterface):
|
||||
"""Interface class for meshtastic devices over a TCP link"""
|
||||
@@ -14,9 +16,9 @@ class TCPInterface(StreamInterface):
|
||||
self,
|
||||
hostname: str,
|
||||
debugOut=None,
|
||||
noProto=False,
|
||||
connectNow=True,
|
||||
portNumber=4403,
|
||||
noProto: bool=False,
|
||||
connectNow: bool=True,
|
||||
portNumber: int=DEFAULT_TCP_PORT,
|
||||
noNodes:bool=False,
|
||||
):
|
||||
"""Constructor, opens a connection to a specified IP address/hostname
|
||||
@@ -27,14 +29,16 @@ class TCPInterface(StreamInterface):
|
||||
|
||||
self.stream = None
|
||||
|
||||
self.hostname = hostname
|
||||
self.portNumber = portNumber
|
||||
self.hostname: str = hostname
|
||||
self.portNumber: int = portNumber
|
||||
|
||||
self.socket: Optional[socket.socket] = None
|
||||
|
||||
if connectNow:
|
||||
logging.debug(f"Connecting to {hostname}") # type: ignore[str-bytes-safe]
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
self.socket: Optional[socket.socket] = sock
|
||||
server_address: tuple[str, int] = (hostname, portNumber)
|
||||
sock: Optional[socket.socket] = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
else:
|
||||
self.socket = None
|
||||
|
||||
@@ -42,25 +46,26 @@ class TCPInterface(StreamInterface):
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes
|
||||
)
|
||||
|
||||
def _socket_shutdown(self):
|
||||
def _socket_shutdown(self) -> None:
|
||||
"""Shutdown the socket.
|
||||
Note: Broke out this line so the exception could be unit tested.
|
||||
"""
|
||||
self.socket.shutdown(socket.SHUT_RDWR)
|
||||
if self.socket: #mian: please check that this should be "if self.socket:"
|
||||
cast(socket.socket, self.socket).shutdown(socket.SHUT_RDWR)
|
||||
|
||||
def myConnect(self):
|
||||
def myConnect(self) -> None:
|
||||
"""Connect to socket"""
|
||||
server_address = (self.hostname, self.portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
server_address: tuple[str, int] = (self.hostname, self.portNumber)
|
||||
sock: Optional[socket.socket] = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
"""Close a connection to the device"""
|
||||
logging.debug("Closing TCP stream")
|
||||
StreamInterface.close(self)
|
||||
# Sometimes the socket read might be blocked in the reader thread.
|
||||
# Therefore we force the shutdown by closing the socket here
|
||||
self._wantExit = True
|
||||
self._wantExit: bool = True
|
||||
if not self.socket is None:
|
||||
try:
|
||||
self._socket_shutdown()
|
||||
@@ -68,10 +73,14 @@ class TCPInterface(StreamInterface):
|
||||
pass # Ignore errors in shutdown, because we might have a race with the server
|
||||
self.socket.close()
|
||||
|
||||
def _writeBytes(self, b):
|
||||
def _writeBytes(self, b: bytes) -> None:
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
self.socket.send(b)
|
||||
if self.socket:
|
||||
self.socket.send(b)
|
||||
|
||||
def _readBytes(self, length):
|
||||
def _readBytes(self, length) -> Optional[bytes]:
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.socket.recv(length)
|
||||
if self.socket:
|
||||
return self.socket.recv(length)
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -5,6 +5,9 @@ import logging
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import io
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
from dotmap import DotMap # type: ignore[import-untyped]
|
||||
from pubsub import pub # type: ignore[import-untyped]
|
||||
@@ -15,19 +18,19 @@ from meshtastic.serial_interface import SerialInterface
|
||||
from meshtastic.tcp_interface import TCPInterface
|
||||
|
||||
"""The interfaces we are using for our tests"""
|
||||
interfaces = None
|
||||
interfaces: List = []
|
||||
|
||||
"""A list of all packets we received while the current test was running"""
|
||||
receivedPackets = None
|
||||
receivedPackets: Optional[List] = None
|
||||
|
||||
testsRunning = False
|
||||
testsRunning: bool = False
|
||||
|
||||
testNumber = 0
|
||||
testNumber: int = 0
|
||||
|
||||
sendingInterface = None
|
||||
|
||||
|
||||
def onReceive(packet, interface):
|
||||
def onReceive(packet, interface) -> None:
|
||||
"""Callback invoked when a packet arrives"""
|
||||
if sendingInterface == interface:
|
||||
pass
|
||||
@@ -42,20 +45,20 @@ def onReceive(packet, interface):
|
||||
receivedPackets.append(p)
|
||||
|
||||
|
||||
def onNode(node):
|
||||
def onNode(node) -> None:
|
||||
"""Callback invoked when the node DB changes"""
|
||||
print(f"Node changed: {node}")
|
||||
|
||||
|
||||
def subscribe():
|
||||
def subscribe() -> None:
|
||||
"""Subscribe to the topics the user probably wants to see, prints output to stdout"""
|
||||
|
||||
pub.subscribe(onNode, "meshtastic.node")
|
||||
|
||||
|
||||
def testSend(
|
||||
fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False
|
||||
):
|
||||
fromInterface, toInterface, isBroadcast: bool=False, asBinary: bool=False, wantAck: bool=False
|
||||
) -> bool:
|
||||
"""
|
||||
Sends one test packet between two nodes and then returns success or failure
|
||||
|
||||
@@ -93,16 +96,16 @@ def testSend(
|
||||
return False # Failed to send
|
||||
|
||||
|
||||
def runTests(numTests=50, wantAck=False, maxFailures=0):
|
||||
def runTests(numTests: int=50, wantAck: bool=False, maxFailures: int=0) -> bool:
|
||||
"""Run the tests."""
|
||||
logging.info(f"Running {numTests} tests with wantAck={wantAck}")
|
||||
numFail = 0
|
||||
numSuccess = 0
|
||||
numFail: int = 0
|
||||
numSuccess: int = 0
|
||||
for _ in range(numTests):
|
||||
# pylint: disable=W0603
|
||||
global testNumber
|
||||
testNumber = testNumber + 1
|
||||
isBroadcast = True
|
||||
isBroadcast:bool = True
|
||||
# asBinary=(i % 2 == 0)
|
||||
success = testSend(
|
||||
interfaces[0], interfaces[1], isBroadcast, asBinary=False, wantAck=wantAck
|
||||
@@ -126,10 +129,10 @@ def runTests(numTests=50, wantAck=False, maxFailures=0):
|
||||
return True
|
||||
|
||||
|
||||
def testThread(numTests=50):
|
||||
def testThread(numTests=50) -> bool:
|
||||
"""Test thread"""
|
||||
logging.info("Found devices, starting tests...")
|
||||
result = runTests(numTests, wantAck=True)
|
||||
result: bool = runTests(numTests, wantAck=True)
|
||||
if result:
|
||||
# Run another test
|
||||
# Allow a few dropped packets
|
||||
@@ -137,25 +140,25 @@ def testThread(numTests=50):
|
||||
return result
|
||||
|
||||
|
||||
def onConnection(topic=pub.AUTO_TOPIC):
|
||||
def onConnection(topic=pub.AUTO_TOPIC) -> None:
|
||||
"""Callback invoked when we connect/disconnect from a radio"""
|
||||
print(f"Connection changed: {topic.getName()}")
|
||||
|
||||
|
||||
def openDebugLog(portName):
|
||||
def openDebugLog(portName) -> io.TextIOWrapper:
|
||||
"""Open the debug log file"""
|
||||
debugname = "log" + portName.replace("/", "_")
|
||||
logging.info(f"Writing serial debugging to {debugname}")
|
||||
return open(debugname, "w+", buffering=1, encoding="utf8")
|
||||
|
||||
|
||||
def testAll(numTests=5):
|
||||
def testAll(numTests: int=5) -> bool:
|
||||
"""
|
||||
Run a series of tests using devices we can find.
|
||||
This is called from the cli with the "--test" option.
|
||||
|
||||
"""
|
||||
ports = meshtastic.util.findPorts(True)
|
||||
ports: List[str] = meshtastic.util.findPorts(True)
|
||||
if len(ports) < 2:
|
||||
meshtastic.util.our_exit(
|
||||
"Warning: Must have at least two devices connected to USB."
|
||||
@@ -175,7 +178,7 @@ def testAll(numTests=5):
|
||||
)
|
||||
|
||||
logging.info("Ports opened, starting test")
|
||||
result = testThread(numTests)
|
||||
result: bool = testThread(numTests)
|
||||
|
||||
for i in interfaces:
|
||||
i.close()
|
||||
@@ -183,7 +186,7 @@ def testAll(numTests=5):
|
||||
return result
|
||||
|
||||
|
||||
def testSimulator():
|
||||
def testSimulator() -> None:
|
||||
"""
|
||||
Assume that someone has launched meshtastic-native as a simulated node.
|
||||
Talk to that node over TCP, do some operations and if they are successful
|
||||
@@ -195,7 +198,7 @@ def testSimulator():
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.info("Connecting to simulator on localhost!")
|
||||
try:
|
||||
iface = TCPInterface("localhost")
|
||||
iface: meshtastic.tcp_interface.TCPInterface = TCPInterface("localhost")
|
||||
iface.showInfo()
|
||||
iface.localNode.showInfo()
|
||||
iface.localNode.exitSimulator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""Meshtastic unit tests for __main__.py"""
|
||||
# pylint: disable=C0302,W0613
|
||||
# pylint: disable=C0302,W0613,R0917
|
||||
|
||||
import logging
|
||||
import os
|
||||
@@ -408,8 +408,8 @@ def test_main_nodes(capsys):
|
||||
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
|
||||
def mock_showNodes():
|
||||
print("inside mocked showNodes")
|
||||
def mock_showNodes(includeSelf, showFields):
|
||||
print(f"inside mocked showNodes: {includeSelf} {showFields}")
|
||||
|
||||
iface.showNodes.side_effect = mock_showNodes
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
@@ -593,10 +593,10 @@ def test_main_sendtext(capsys):
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
|
||||
def mock_sendText(
|
||||
text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0
|
||||
text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0, portNum=0
|
||||
):
|
||||
print("inside mocked sendText")
|
||||
print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex}")
|
||||
print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex} {portNum}")
|
||||
|
||||
iface.sendText.side_effect = mock_sendText
|
||||
|
||||
@@ -620,10 +620,10 @@ def test_main_sendtext_with_channel(capsys):
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
|
||||
def mock_sendText(
|
||||
text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0
|
||||
text, dest, wantAck=False, wantResponse=False, onResponse=None, channelIndex=0, portNum=0
|
||||
):
|
||||
print("inside mocked sendText")
|
||||
print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex}")
|
||||
print(f"{text} {dest} {wantAck} {wantResponse} {channelIndex} {portNum}")
|
||||
|
||||
iface.sendText.side_effect = mock_sendText
|
||||
|
||||
@@ -726,8 +726,8 @@ def test_main_sendtext_with_dest(mock_findPorts, mock_serial, mocked_open, mock_
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_main_removeposition_invalid(capsys):
|
||||
"""Test --remove-position with an invalid dest"""
|
||||
def test_main_removeposition_remote(capsys):
|
||||
"""Test --remove-position with a remote dest"""
|
||||
sys.argv = ["", "--remove-position", "--dest", "!12345678"]
|
||||
mt_config.args = sys.argv
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
@@ -735,14 +735,15 @@ def test_main_removeposition_invalid(capsys):
|
||||
main()
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r"Connected to radio", out, re.MULTILINE)
|
||||
assert re.search(r"remote nodes is not supported", out, re.MULTILINE)
|
||||
assert re.search(r"Removing fixed position and disabling fixed position setting", out, re.MULTILINE)
|
||||
assert re.search(r"Waiting for an acknowledgment from remote node", out, re.MULTILINE)
|
||||
assert err == ""
|
||||
mo.assert_called()
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_main_setlat_invalid(capsys):
|
||||
"""Test --setlat with an invalid dest"""
|
||||
def test_main_setlat_remote(capsys):
|
||||
"""Test --setlat with a remote dest"""
|
||||
sys.argv = ["", "--setlat", "37.5", "--dest", "!12345678"]
|
||||
mt_config.args = sys.argv
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
@@ -750,7 +751,8 @@ def test_main_setlat_invalid(capsys):
|
||||
main()
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r"Connected to radio", out, re.MULTILINE)
|
||||
assert re.search(r"remote nodes is not supported", out, re.MULTILINE)
|
||||
assert re.search(r"Setting device position and enabling fixed position setting", out, re.MULTILINE)
|
||||
assert re.search(r"Waiting for an acknowledgment from remote node", out, re.MULTILINE)
|
||||
assert err == ""
|
||||
mo.assert_called()
|
||||
|
||||
@@ -769,7 +771,7 @@ def test_main_removeposition(capsys):
|
||||
mocked_node.removeFixedPosition.side_effect = mock_removeFixedPosition
|
||||
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.localNode = mocked_node
|
||||
iface.getNode.return_value = mocked_node
|
||||
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
main()
|
||||
@@ -796,7 +798,7 @@ def test_main_setlat(capsys):
|
||||
mocked_node.setFixedPosition.side_effect = mock_setFixedPosition
|
||||
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.localNode = mocked_node
|
||||
iface.getNode.return_value = mocked_node
|
||||
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
main()
|
||||
@@ -825,7 +827,7 @@ def test_main_setlon(capsys):
|
||||
mocked_node.setFixedPosition.side_effect = mock_setFixedPosition
|
||||
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.localNode = mocked_node
|
||||
iface.getNode.return_value = mocked_node
|
||||
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
main()
|
||||
@@ -854,7 +856,7 @@ def test_main_setalt(capsys):
|
||||
mocked_node.setFixedPosition.side_effect = mock_setFixedPosition
|
||||
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.localNode = mocked_node
|
||||
iface.getNode.return_value = mocked_node
|
||||
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
main()
|
||||
@@ -1606,7 +1608,7 @@ def test_main_onReceive_empty(caplog, capsys):
|
||||
assert re.search(r"in onReceive", caplog.text, re.MULTILINE)
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(
|
||||
r"Warning: There is no field 'to' in the packet.", out, re.MULTILINE
|
||||
r"Warning: Error processing received packet: 'to'.", out, re.MULTILINE
|
||||
)
|
||||
assert err == ""
|
||||
|
||||
@@ -2650,3 +2652,64 @@ def test_tunnel_tunnel_arg(
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r"Connected to radio", out, re.MULTILINE)
|
||||
assert err == ""
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_set_favorite_node():
|
||||
"""Test --set-favorite-node node"""
|
||||
sys.argv = ["", "--set-favorite-node", "!12345678"]
|
||||
mt_config.args = sys.argv
|
||||
mocked_node = MagicMock(autospec=Node)
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.getNode.return_value = mocked_node
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
|
||||
main()
|
||||
|
||||
mocked_node.setFavorite.assert_called_once_with("!12345678")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_remove_favorite_node():
|
||||
"""Test --remove-favorite-node node"""
|
||||
sys.argv = ["", "--remove-favorite-node", "!12345678"]
|
||||
mt_config.args = sys.argv
|
||||
mocked_node = MagicMock(autospec=Node)
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.getNode.return_value = mocked_node
|
||||
mocked_node.iface = iface
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
|
||||
main()
|
||||
|
||||
mocked_node.removeFavorite.assert_called_once_with("!12345678")
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_set_ignored_node():
|
||||
"""Test --set-ignored-node node"""
|
||||
sys.argv = ["", "--set-ignored-node", "!12345678"]
|
||||
mt_config.args = sys.argv
|
||||
mocked_node = MagicMock(autospec=Node)
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.getNode.return_value = mocked_node
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
|
||||
main()
|
||||
|
||||
mocked_node.setIgnored.assert_called_once_with("!12345678")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_remove_ignored_node():
|
||||
"""Test --remove-ignored-node node"""
|
||||
sys.argv = ["", "--remove-ignored-node", "!12345678"]
|
||||
mt_config.args = sys.argv
|
||||
mocked_node = MagicMock(autospec=Node)
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
iface.getNode.return_value = mocked_node
|
||||
mocked_node.iface = iface
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):
|
||||
main()
|
||||
|
||||
mocked_node.removeIgnored.assert_called_once_with("!12345678")
|
||||
|
||||
@@ -173,7 +173,23 @@ def test_getNode_not_local_timeout(capsys):
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert re.match(r"Error: Timed out waiting for channels", out)
|
||||
assert re.match(r"Timed out trying to retrieve channel info, retrying", out)
|
||||
assert err == ""
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.usefixtures("reset_mt_config")
|
||||
def test_getNode_not_local_timeout_attempts(capsys):
|
||||
"""Test getNode not local, simulate timeout"""
|
||||
iface = MeshInterface(noProto=True)
|
||||
anode = MagicMock(autospec=Node)
|
||||
anode.waitForConfig.return_value = False
|
||||
with patch("meshtastic.node.Node", return_value=anode):
|
||||
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
||||
iface.getNode("bar2", requestChannelAttempts=2)
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert out == 'Timed out trying to retrieve channel info, retrying\nError: Timed out waiting for channels, giving up\n'
|
||||
assert err == ""
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from ..protobuf import localonly_pb2, config_pb2
|
||||
from ..protobuf import admin_pb2, localonly_pb2, config_pb2
|
||||
from ..protobuf.channel_pb2 import Channel # pylint: disable=E0611
|
||||
from ..node import Node
|
||||
from ..serial_interface import SerialInterface
|
||||
@@ -231,7 +231,9 @@ def test_node(capsys):
|
||||
@pytest.mark.unit
|
||||
def test_exitSimulator(caplog):
|
||||
"""Test exitSimulator"""
|
||||
anode = Node("foo", "bar", noProto=True)
|
||||
interface = MeshInterface()
|
||||
interface.nodesByNum = {}
|
||||
anode = Node(interface, "!ba400000", noProto=True)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
anode.exitSimulator()
|
||||
assert re.search(r"in exitSimulator", caplog.text, re.MULTILINE)
|
||||
@@ -240,7 +242,9 @@ def test_exitSimulator(caplog):
|
||||
@pytest.mark.unit
|
||||
def test_reboot(caplog):
|
||||
"""Test reboot"""
|
||||
anode = Node(MeshInterface(), 1234567890, noProto=True)
|
||||
interface = MeshInterface()
|
||||
interface.nodesByNum = {}
|
||||
anode = Node(interface, 1234567890, noProto=True)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
anode.reboot()
|
||||
assert re.search(r"Telling node to reboot", caplog.text, re.MULTILINE)
|
||||
@@ -249,7 +253,9 @@ def test_reboot(caplog):
|
||||
@pytest.mark.unit
|
||||
def test_shutdown(caplog):
|
||||
"""Test shutdown"""
|
||||
anode = Node(MeshInterface(), 1234567890, noProto=True)
|
||||
interface = MeshInterface()
|
||||
interface.nodesByNum = {}
|
||||
anode = Node(interface, 1234567890, noProto=True)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
anode.shutdown()
|
||||
assert re.search(r"Telling node to shutdown", caplog.text, re.MULTILINE)
|
||||
@@ -264,7 +270,7 @@ def test_setURL_empty_url(capsys):
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r"Warning: There were no settings.", out, re.MULTILINE)
|
||||
assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE)
|
||||
assert err == ""
|
||||
|
||||
|
||||
@@ -298,7 +304,7 @@ def test_setURL_valid_URL_but_no_settings(capsys):
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r"Warning: There were no settings", out, re.MULTILINE)
|
||||
assert re.search(r"Warning: config or channels not loaded", out, re.MULTILINE)
|
||||
assert err == ""
|
||||
|
||||
|
||||
@@ -836,6 +842,34 @@ def test_requestChannel_localNode(caplog):
|
||||
assert re.search(r"Requesting channel 0", caplog.text, re.MULTILINE)
|
||||
assert not re.search(r"from remote node", caplog.text, re.MULTILINE)
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_requestChannels_non_localNode(caplog):
|
||||
"""Test requestChannels() with a starting index of 0"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
mo.localNode.getChannelByName.return_value = None
|
||||
mo.myInfo.max_channels = 8
|
||||
anode = Node(mo, "bar", noProto=True)
|
||||
anode.partialChannels = ['0']
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
anode.requestChannels(0)
|
||||
assert re.search(f"Requesting channel 0 info from remote node", caplog.text, re.MULTILINE)
|
||||
assert anode.partialChannels == []
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_requestChannels_non_localNode_starting_index(caplog):
|
||||
"""Test requestChannels() with a starting index of non-0"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
|
||||
mo.localNode.getChannelByName.return_value = None
|
||||
mo.myInfo.max_channels = 8
|
||||
anode = Node(mo, "bar", noProto=True)
|
||||
anode.partialChannels = ['1']
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
anode.requestChannels(3)
|
||||
assert re.search(f"Requesting channel 3 info from remote node", caplog.text, re.MULTILINE)
|
||||
# make sure it hasn't been initialized
|
||||
assert anode.partialChannels == ['1']
|
||||
|
||||
# @pytest.mark.unit
|
||||
# def test_onResponseRequestCannedMessagePluginMesagePart1(caplog):
|
||||
@@ -1392,6 +1426,60 @@ def test_requestChannel_localNode(caplog):
|
||||
# assert err == ''
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize("favorite", ["!1dec0ded", 502009325])
|
||||
def test_set_favorite(favorite):
|
||||
"""Test setFavorite"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
node = Node(iface, 12345678)
|
||||
amesg = admin_pb2.AdminMessage()
|
||||
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
|
||||
node.setFavorite(favorite)
|
||||
assert amesg.set_favorite_node == 502009325
|
||||
iface.sendData.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize("favorite", ["!1dec0ded", 502009325])
|
||||
def test_remove_favorite(favorite):
|
||||
"""Test setFavorite"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
node = Node(iface, 12345678)
|
||||
amesg = admin_pb2.AdminMessage()
|
||||
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
|
||||
node.removeFavorite(favorite)
|
||||
|
||||
assert amesg.remove_favorite_node == 502009325
|
||||
iface.sendData.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize("ignored", ["!1dec0ded", 502009325])
|
||||
def test_set_ignored(ignored):
|
||||
"""Test setFavorite"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
node = Node(iface, 12345678)
|
||||
amesg = admin_pb2.AdminMessage()
|
||||
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
|
||||
node.setIgnored(ignored)
|
||||
assert amesg.set_ignored_node == 502009325
|
||||
iface.sendData.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.parametrize("ignored", ["!1dec0ded", 502009325])
|
||||
def test_remove_ignored(ignored):
|
||||
"""Test setFavorite"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
node = Node(iface, 12345678)
|
||||
amesg = admin_pb2.AdminMessage()
|
||||
with patch("meshtastic.admin_pb2.AdminMessage", return_value=amesg):
|
||||
node.removeIgnored(ignored)
|
||||
|
||||
assert amesg.remove_ignored_node == 502009325
|
||||
iface.sendData.assert_called_once()
|
||||
|
||||
|
||||
# TODO
|
||||
# @pytest.mark.unitslow
|
||||
# def test_waitForConfig():
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Meshtastic unit tests for serial_interface.py"""
|
||||
# pylint: disable=R0917
|
||||
|
||||
import re
|
||||
from unittest.mock import mock_open, patch
|
||||
|
||||
@@ -442,6 +442,13 @@ def test_is_windows11_false_win8_1(patched_platform, patched_release):
|
||||
patched_platform.assert_called()
|
||||
patched_release.assert_called()
|
||||
|
||||
@patch("platform.release", return_value="2022Server")
|
||||
@patch("platform.system", return_value="Windows")
|
||||
def test_is_windows11_false_winserver(patched_platform, patched_release):
|
||||
"""Test is_windows11()"""
|
||||
assert is_windows11() is False
|
||||
patched_platform.assert_called()
|
||||
patched_release.assert_called()
|
||||
|
||||
@pytest.mark.unit
|
||||
@patch("platform.system", return_value="Linux")
|
||||
@@ -556,7 +563,7 @@ def test_active_ports_on_supported_devices_mac_duplicates_check(mock_platform, m
|
||||
def test_message_to_json_shows_all():
|
||||
"""Test that message_to_json prints fields that aren't included in data passed in"""
|
||||
actual = json.loads(message_to_json(mesh_pb2.MyNodeInfo()))
|
||||
expected = { "myNodeNum": 0, "rebootCount": 0, "minAppVersion": 0 }
|
||||
expected = { "myNodeNum": 0, "rebootCount": 0, "minAppVersion": 0, "deviceId": "", "pioEnv": "" }
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.unit
|
||||
@@ -594,3 +601,72 @@ def test_roundtrip_snake_to_camel_camel_to_snake(a_string):
|
||||
value0 = snake_to_camel(a_string=a_string)
|
||||
value1 = camel_to_snake(a_string=value0)
|
||||
assert a_string == value1, (a_string, value1)
|
||||
|
||||
@given(st.text())
|
||||
def test_fuzz_camel_to_snake(a_string):
|
||||
"""Test that camel_to_snake produces outputs with underscores for multi-word camelcase"""
|
||||
result = camel_to_snake(a_string)
|
||||
assert "_" in result or result == a_string.lower().replace("_", "")
|
||||
|
||||
@given(st.text())
|
||||
def test_fuzz_snake_to_camel(a_string):
|
||||
"""Test that snake_to_camel removes underscores"""
|
||||
result = snake_to_camel(a_string)
|
||||
assert "_" not in result or result == a_string.split("_")[0] + "".join(ele.title() for ele in a_string.split("_")[1:])
|
||||
|
||||
@given(st.text())
|
||||
def test_fuzz_stripnl(s):
|
||||
"""Test that stripnl always takes away newlines"""
|
||||
result = stripnl(s)
|
||||
assert "\n" not in result
|
||||
|
||||
@given(st.binary())
|
||||
def test_fuzz_pskToString(psk):
|
||||
"""Test that pskToString produces sane output for any bytes"""
|
||||
result = pskToString(psk)
|
||||
if len(psk) == 0:
|
||||
assert result == "unencrypted"
|
||||
elif len(psk) == 1:
|
||||
b = psk[0]
|
||||
if b == 0:
|
||||
assert result == "unencrypted"
|
||||
elif b == 1:
|
||||
assert result == "default"
|
||||
else:
|
||||
assert result == f"simple{b - 1}"
|
||||
else:
|
||||
assert result == "secret"
|
||||
|
||||
@given(st.text())
|
||||
def test_fuzz_fromStr(valstr):
|
||||
"""Test that fromStr produces mostly-useful output given any string"""
|
||||
result = fromStr(valstr)
|
||||
if valstr.startswith("0x"):
|
||||
assert isinstance(result, bytes)
|
||||
elif valstr.startswith("base64:"):
|
||||
assert isinstance(result, bytes)
|
||||
elif len(valstr) == 0:
|
||||
assert result == b''
|
||||
elif valstr.lower() in {"t", "true", "yes"}:
|
||||
assert result is True
|
||||
elif valstr.lower() in {"f", "false", "no"}:
|
||||
assert result is False
|
||||
else:
|
||||
try:
|
||||
int(valstr)
|
||||
assert isinstance(result, int)
|
||||
except ValueError:
|
||||
try:
|
||||
float(valstr)
|
||||
assert isinstance(result, float)
|
||||
except ValueError:
|
||||
assert isinstance(result, str)
|
||||
|
||||
def test_shorthex():
|
||||
"""Test the shortest hex string representations"""
|
||||
result = fromStr('0x0')
|
||||
assert result == b'\x00'
|
||||
result = fromStr('0x5')
|
||||
assert result == b'\x05'
|
||||
result = fromStr('0xffff')
|
||||
assert result == b'\xff\xff'
|
||||
|
||||
@@ -43,7 +43,7 @@ class Tunnel:
|
||||
self.message = message
|
||||
super().__init__(self.message)
|
||||
|
||||
def __init__(self, iface, subnet="10.115", netmask="255.255.0.0"):
|
||||
def __init__(self, iface, subnet: str="10.115", netmask: str="255.255.0.0") -> None:
|
||||
"""
|
||||
Constructor
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import threading
|
||||
import time
|
||||
import traceback
|
||||
from queue import Queue
|
||||
from typing import List, NoReturn, Union
|
||||
from typing import Any, Dict, List, NoReturn, Optional, Set, Tuple, Union
|
||||
|
||||
from google.protobuf.json_format import MessageToJson
|
||||
from google.protobuf.message import Message
|
||||
@@ -31,7 +31,7 @@ from meshtastic.version import get_active_version
|
||||
0925 Lakeview Research Saleae Logic (logic analyzer)
|
||||
04b4:602a Cypress Semiconductor Corp. Hantek DSO-6022BL (oscilloscope)
|
||||
"""
|
||||
blacklistVids = dict.fromkeys([0x1366, 0x0483, 0x1915, 0x0925, 0x04b4])
|
||||
blacklistVids: Dict = dict.fromkeys([0x1366, 0x0483, 0x1915, 0x0925, 0x04b4])
|
||||
|
||||
"""Some devices are highly likely to be meshtastic.
|
||||
0x239a RAK4631
|
||||
@@ -39,21 +39,21 @@ blacklistVids = dict.fromkeys([0x1366, 0x0483, 0x1915, 0x0925, 0x04b4])
|
||||
whitelistVids = dict.fromkeys([0x239a, 0x303a])
|
||||
|
||||
|
||||
def quoteBooleans(a_string):
|
||||
def quoteBooleans(a_string: str) -> str:
|
||||
"""Quote booleans
|
||||
given a string that contains ": true", replace with ": 'true'" (or false)
|
||||
"""
|
||||
tmp = a_string.replace(": true", ": 'true'")
|
||||
tmp: str = a_string.replace(": true", ": 'true'")
|
||||
tmp = tmp.replace(": false", ": 'false'")
|
||||
return tmp
|
||||
|
||||
|
||||
def genPSK256():
|
||||
def genPSK256() -> bytes:
|
||||
"""Generate a random preshared key"""
|
||||
return os.urandom(32)
|
||||
|
||||
|
||||
def fromPSK(valstr):
|
||||
def fromPSK(valstr: str) -> Any:
|
||||
"""A special version of fromStr that assumes the user is trying to set a PSK.
|
||||
In that case we also allow "none", "default" or "random" (to have python generate one), or simpleN
|
||||
"""
|
||||
@@ -70,7 +70,7 @@ def fromPSK(valstr):
|
||||
return fromStr(valstr)
|
||||
|
||||
|
||||
def fromStr(valstr):
|
||||
def fromStr(valstr: str) -> Any:
|
||||
"""Try to parse as int, float or bool (and fallback to a string as last resort)
|
||||
|
||||
Returns: an int, bool, float, str or byte array (for strings of hex digits)
|
||||
@@ -78,11 +78,12 @@ def fromStr(valstr):
|
||||
Args:
|
||||
valstr (string): A user provided string
|
||||
"""
|
||||
val: Any
|
||||
if len(valstr) == 0: # Treat an emptystring as an empty bytes
|
||||
val = bytes()
|
||||
elif valstr.startswith("0x"):
|
||||
# if needed convert to string with asBytes.decode('utf-8')
|
||||
val = bytes.fromhex(valstr[2:])
|
||||
val = bytes.fromhex(valstr[2:].zfill(2))
|
||||
elif valstr.startswith("base64:"):
|
||||
val = base64.b64decode(valstr[7:])
|
||||
elif valstr.lower() in {"t", "true", "yes"}:
|
||||
@@ -100,7 +101,15 @@ def fromStr(valstr):
|
||||
return val
|
||||
|
||||
|
||||
def pskToString(psk: bytes):
|
||||
|
||||
def toStr(raw_value):
|
||||
"""Convert a value to a string that can be used in a config file"""
|
||||
if isinstance(raw_value, bytes):
|
||||
return "base64:" + base64.b64encode(raw_value).decode("utf-8")
|
||||
return str(raw_value)
|
||||
|
||||
|
||||
def pskToString(psk: bytes) -> str:
|
||||
"""Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string"""
|
||||
if len(psk) == 0:
|
||||
return "unencrypted"
|
||||
@@ -122,12 +131,12 @@ def stripnl(s) -> str:
|
||||
return " ".join(s.split())
|
||||
|
||||
|
||||
def fixme(message):
|
||||
def fixme(message: str) -> None:
|
||||
"""Raise an exception for things that needs to be fixed"""
|
||||
raise Exception(f"FIXME: {message}") # pylint: disable=W0719
|
||||
|
||||
|
||||
def catchAndIgnore(reason, closure):
|
||||
def catchAndIgnore(reason: str, closure) -> None:
|
||||
"""Call a closure but if it throws an exception print it and continue"""
|
||||
try:
|
||||
closure()
|
||||
@@ -145,7 +154,7 @@ def findPorts(eliminate_duplicates: bool=False) -> List[str]:
|
||||
all_ports = serial.tools.list_ports.comports()
|
||||
|
||||
# look for 'likely' meshtastic devices
|
||||
ports = list(
|
||||
ports: List = list(
|
||||
map(
|
||||
lambda port: port.device,
|
||||
filter(
|
||||
@@ -184,12 +193,12 @@ class dotdict(dict):
|
||||
class Timeout:
|
||||
"""Timeout class"""
|
||||
|
||||
def __init__(self, maxSecs: int=20):
|
||||
def __init__(self, maxSecs: int=20) -> None:
|
||||
self.expireTime: Union[int, float] = 0
|
||||
self.sleepInterval: float = 0.1
|
||||
self.expireTimeout: int = maxSecs
|
||||
|
||||
def reset(self):
|
||||
def reset(self) -> None:
|
||||
"""Restart the waitForSet timer"""
|
||||
self.expireTime = time.time() + self.expireTimeout
|
||||
|
||||
@@ -245,10 +254,20 @@ class Timeout:
|
||||
time.sleep(self.sleepInterval)
|
||||
return False
|
||||
|
||||
def waitForWaypoint(self, acknowledgment) -> bool:
|
||||
"""Block until waypoint response is received. Returns True if waypoint response has been received."""
|
||||
self.reset()
|
||||
while time.time() < self.expireTime:
|
||||
if getattr(acknowledgment, "receivedWaypoint", None):
|
||||
acknowledgment.reset()
|
||||
return True
|
||||
time.sleep(self.sleepInterval)
|
||||
return False
|
||||
|
||||
class Acknowledgment:
|
||||
"A class that records which type of acknowledgment was just received, if any."
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self) -> None:
|
||||
"""initialize"""
|
||||
self.receivedAck = False
|
||||
self.receivedNak = False
|
||||
@@ -256,8 +275,9 @@ class Acknowledgment:
|
||||
self.receivedTraceRoute = False
|
||||
self.receivedTelemetry = False
|
||||
self.receivedPosition = False
|
||||
self.receivedWaypoint = False
|
||||
|
||||
def reset(self):
|
||||
def reset(self) -> None:
|
||||
"""reset"""
|
||||
self.receivedAck = False
|
||||
self.receivedNak = False
|
||||
@@ -265,23 +285,24 @@ class Acknowledgment:
|
||||
self.receivedTraceRoute = False
|
||||
self.receivedTelemetry = False
|
||||
self.receivedPosition = False
|
||||
self.receivedWaypoint = False
|
||||
|
||||
|
||||
class DeferredExecution:
|
||||
"""A thread that accepts closures to run, and runs them as they are received"""
|
||||
|
||||
def __init__(self, name):
|
||||
self.queue = Queue()
|
||||
def __init__(self, name) -> None:
|
||||
self.queue: Queue = Queue()
|
||||
# this thread must be marked as daemon, otherwise it will prevent clients from exiting
|
||||
self.thread = threading.Thread(target=self._run, args=(), name=name, daemon=True)
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
|
||||
def queueWork(self, runnable):
|
||||
def queueWork(self, runnable) -> None:
|
||||
"""Queue up the work"""
|
||||
self.queue.put(runnable)
|
||||
|
||||
def _run(self):
|
||||
def _run(self) -> None:
|
||||
while True:
|
||||
try:
|
||||
o = self.queue.get()
|
||||
@@ -301,7 +322,7 @@ def our_exit(message, return_value=1) -> NoReturn:
|
||||
sys.exit(return_value)
|
||||
|
||||
|
||||
def support_info():
|
||||
def support_info() -> None:
|
||||
"""Print out info that helps troubleshooting of the cli."""
|
||||
print("")
|
||||
print("If having issues with meshtastic cli or python library")
|
||||
@@ -330,7 +351,7 @@ def support_info():
|
||||
print("Please add the output from the command: meshtastic --info")
|
||||
|
||||
|
||||
def remove_keys_from_dict(keys, adict):
|
||||
def remove_keys_from_dict(keys: Union[Tuple, List, Set], adict: Dict) -> Dict:
|
||||
"""Return a dictionary without some keys in it.
|
||||
Will removed nested keys.
|
||||
"""
|
||||
@@ -345,33 +366,33 @@ def remove_keys_from_dict(keys, adict):
|
||||
return adict
|
||||
|
||||
|
||||
def hexstr(barray):
|
||||
def hexstr(barray: bytes) -> str:
|
||||
"""Print a string of hex digits"""
|
||||
return ":".join(f"{x:02x}" for x in barray)
|
||||
|
||||
|
||||
def ipstr(barray):
|
||||
def ipstr(barray: bytes) -> str:
|
||||
"""Print a string of ip digits"""
|
||||
return ".".join(f"{x}" for x in barray)
|
||||
|
||||
|
||||
def readnet_u16(p, offset):
|
||||
def readnet_u16(p, offset: int) -> int:
|
||||
"""Read big endian u16 (network byte order)"""
|
||||
return p[offset] * 256 + p[offset + 1]
|
||||
|
||||
|
||||
def convert_mac_addr(val):
|
||||
def convert_mac_addr(val: str) -> Union[str, bytes]:
|
||||
"""Convert the base 64 encoded value to a mac address
|
||||
val - base64 encoded value (ex: '/c0gFyhb'))
|
||||
returns: a string formatted like a mac address (ex: 'fd:cd:20:17:28:5b')
|
||||
"""
|
||||
if not re.match("[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", val):
|
||||
val_as_bytes = base64.b64decode(val)
|
||||
val_as_bytes: bytes = base64.b64decode(val)
|
||||
return hexstr(val_as_bytes)
|
||||
return val
|
||||
|
||||
|
||||
def snake_to_camel(a_string):
|
||||
def snake_to_camel(a_string: str) -> str:
|
||||
"""convert snake_case to camelCase"""
|
||||
# split underscore using split
|
||||
temp = a_string.split("_")
|
||||
@@ -380,16 +401,16 @@ def snake_to_camel(a_string):
|
||||
return result
|
||||
|
||||
|
||||
def camel_to_snake(a_string):
|
||||
def camel_to_snake(a_string: str) -> str:
|
||||
"""convert camelCase to snake_case"""
|
||||
return "".join(["_" + i.lower() if i.isupper() else i for i in a_string]).lstrip(
|
||||
"_"
|
||||
)
|
||||
|
||||
|
||||
def detect_supported_devices():
|
||||
def detect_supported_devices() -> Set:
|
||||
"""detect supported devices based on vendor id"""
|
||||
system = platform.system()
|
||||
system: str = platform.system()
|
||||
# print(f'system:{system}')
|
||||
|
||||
possible_devices = set()
|
||||
@@ -447,9 +468,9 @@ def detect_supported_devices():
|
||||
return possible_devices
|
||||
|
||||
|
||||
def detect_windows_needs_driver(sd, print_reason=False):
|
||||
def detect_windows_needs_driver(sd, print_reason=False) -> bool:
|
||||
"""detect if Windows user needs to install driver for a supported device"""
|
||||
need_to_install_driver = False
|
||||
need_to_install_driver: bool = False
|
||||
|
||||
if sd:
|
||||
system = platform.system()
|
||||
@@ -475,7 +496,7 @@ def detect_windows_needs_driver(sd, print_reason=False):
|
||||
return need_to_install_driver
|
||||
|
||||
|
||||
def eliminate_duplicate_port(ports):
|
||||
def eliminate_duplicate_port(ports: List) -> List:
|
||||
"""Sometimes we detect 2 serial ports, but we really only need to use one of the ports.
|
||||
|
||||
ports is a list of ports
|
||||
@@ -508,23 +529,23 @@ def eliminate_duplicate_port(ports):
|
||||
return new_ports
|
||||
|
||||
|
||||
def is_windows11():
|
||||
def is_windows11() -> bool:
|
||||
"""Detect if Windows 11"""
|
||||
is_win11 = False
|
||||
is_win11: bool = False
|
||||
if platform.system() == "Windows":
|
||||
if float(platform.release()) >= 10.0:
|
||||
patch = platform.version().split(".")[2]
|
||||
# in case they add some number suffix later, just get first 5 chars of patch
|
||||
patch = patch[:5]
|
||||
try:
|
||||
try:
|
||||
if float(platform.release()) >= 10.0:
|
||||
patch = platform.version().split(".")[2]
|
||||
# in case they add some number suffix later, just get first 5 chars of patch
|
||||
patch = patch[:5]
|
||||
if int(patch) >= 22000:
|
||||
is_win11 = True
|
||||
except Exception as e:
|
||||
print(f"problem detecting win11 e:{e}")
|
||||
except Exception as e:
|
||||
print(f"problem detecting win11 e:{e}")
|
||||
return is_win11
|
||||
|
||||
|
||||
def get_unique_vendor_ids():
|
||||
def get_unique_vendor_ids() -> Set[str]:
|
||||
"""Return a set of unique vendor ids"""
|
||||
vids = set()
|
||||
for d in supported_devices:
|
||||
@@ -533,7 +554,7 @@ def get_unique_vendor_ids():
|
||||
return vids
|
||||
|
||||
|
||||
def get_devices_with_vendor_id(vid):
|
||||
def get_devices_with_vendor_id(vid: str) -> Set: #Set[SupportedDevice]
|
||||
"""Return a set of unique devices with the vendor id"""
|
||||
sd = set()
|
||||
for d in supported_devices:
|
||||
@@ -542,11 +563,11 @@ def get_devices_with_vendor_id(vid):
|
||||
return sd
|
||||
|
||||
|
||||
def active_ports_on_supported_devices(sds, eliminate_duplicates=False):
|
||||
def active_ports_on_supported_devices(sds, eliminate_duplicates=False) -> Set[str]:
|
||||
"""Return a set of active ports based on the supplied supported devices"""
|
||||
ports = set()
|
||||
baseports = set()
|
||||
system = platform.system()
|
||||
ports: Set = set()
|
||||
baseports: Set = set()
|
||||
system: str = platform.system()
|
||||
|
||||
# figure out what possible base ports there are
|
||||
for d in sds:
|
||||
@@ -604,13 +625,13 @@ def active_ports_on_supported_devices(sds, eliminate_duplicates=False):
|
||||
for com_port in com_ports:
|
||||
ports.add(com_port)
|
||||
if eliminate_duplicates:
|
||||
ports = eliminate_duplicate_port(list(ports))
|
||||
ports.sort()
|
||||
ports = set(ports)
|
||||
portlist: List = eliminate_duplicate_port(list(ports))
|
||||
portlist.sort()
|
||||
ports = set(portlist)
|
||||
return ports
|
||||
|
||||
|
||||
def detect_windows_port(sd):
|
||||
def detect_windows_port(sd) -> Set[str]: #"sd" is a SupportedDevice from meshtastic.supported_device
|
||||
"""detect if Windows port"""
|
||||
ports = set()
|
||||
|
||||
@@ -635,20 +656,26 @@ def detect_windows_port(sd):
|
||||
return ports
|
||||
|
||||
|
||||
def check_if_newer_version():
|
||||
def check_if_newer_version() -> Optional[str]:
|
||||
"""Check pip to see if we are running the latest version."""
|
||||
pypi_version = None
|
||||
pypi_version: Optional[str] = None
|
||||
try:
|
||||
url = "https://pypi.org/pypi/meshtastic/json"
|
||||
url: str = "https://pypi.org/pypi/meshtastic/json"
|
||||
data = requests.get(url, timeout=5).json()
|
||||
pypi_version = data["info"]["version"]
|
||||
except Exception:
|
||||
pass
|
||||
act_version = get_active_version()
|
||||
|
||||
if pypi_version is None:
|
||||
return None
|
||||
try:
|
||||
parsed_act_version = pkg_version.parse(act_version)
|
||||
parsed_pypi_version = pkg_version.parse(pypi_version)
|
||||
#Note: if handed "None" when we can't download the pypi_version,
|
||||
#this gets a TypeError:
|
||||
#"TypeError: expected string or bytes-like object, got 'NoneType'"
|
||||
#Handle that below?
|
||||
except pkg_version.InvalidVersion:
|
||||
return pypi_version
|
||||
|
||||
@@ -660,5 +687,8 @@ def check_if_newer_version():
|
||||
|
||||
def message_to_json(message: Message, multiline: bool=False) -> str:
|
||||
"""Return protobuf message as JSON. Always print all fields, even when not present in data."""
|
||||
json = MessageToJson(message, always_print_fields_with_no_presence=True)
|
||||
try:
|
||||
json = MessageToJson(message, always_print_fields_with_no_presence=True)
|
||||
except TypeError:
|
||||
json = MessageToJson(message, including_default_value_fields=True) # type: ignore[call-arg] # pylint: disable=E1123
|
||||
return stripnl(json) if not multiline else json
|
||||
|
||||
3167
poetry.lock
generated
3167
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
Submodule protobufs updated: 666b481ae0...2a3a67f043
@@ -1,31 +1,31 @@
|
||||
[tool.poetry]
|
||||
name = "meshtastic"
|
||||
version = "2.4.3"
|
||||
version = "2.6.0a1"
|
||||
description = "Python API & client shell for talking to Meshtastic devices"
|
||||
authors = ["Meshtastic Developers <contact@meshtastic.org>"]
|
||||
license = "GPL-3.0-only"
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9,<3.13" # 3.9 is needed for pandas, bleak requires a max of 3.13 for some reason
|
||||
python = "^3.9,<3.14" # 3.9 is needed for pandas, bleak requires <3.14
|
||||
pyserial = "^3.5"
|
||||
protobuf = ">=5.26.0"
|
||||
dotmap = "^1.3.30"
|
||||
pexpect = "^4.9.0"
|
||||
pyqrcode = "^1.2.1"
|
||||
protobuf = ">=4.21.12"
|
||||
tabulate = "^0.9.0"
|
||||
webencodings = "^0.5.1"
|
||||
requests = "^2.31.0"
|
||||
pyparsing = "^3.1.2"
|
||||
pyyaml = "^6.0.1"
|
||||
pypubsub = "^4.0.3"
|
||||
bleak = "^0.21.1"
|
||||
bleak = "^0.22.3"
|
||||
packaging = "^24.0"
|
||||
print-color = "^0.4.6"
|
||||
argcomplete = { version = "^3.5.2", optional = true }
|
||||
pyqrcode = { version = "^1.2.1", optional = true }
|
||||
dotmap = { version = "^1.3.30", optional = true }
|
||||
print-color = { version = "^0.4.6", optional = true }
|
||||
dash = { version = "^2.17.1", optional = true }
|
||||
pytap2 = { version = "^2.3.0", optional = true }
|
||||
dash-bootstrap-components = { version = "^1.6.0", optional = true }
|
||||
pandas = { version = "^2.2.2", optional = true }
|
||||
pandas-stubs = { version = "^2.2.2.240603", optional = true }
|
||||
wcwidth = {version = "^0.2.13", optional = true}
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
hypothesis = "^6.103.2"
|
||||
@@ -36,14 +36,13 @@ autopep8 = "^2.1.0"
|
||||
pylint = "^3.2.3"
|
||||
pyinstaller = "^6.8.0"
|
||||
mypy = "^1.10.0"
|
||||
mypy-protobuf = "^3.6.0"
|
||||
mypy-protobuf = "^3.3.0"
|
||||
types-protobuf = "^5.26.0.20240422"
|
||||
types-tabulate = "^0.9.0.20240106"
|
||||
types-requests = "^2.31.0.20240406"
|
||||
types-setuptools = "^69.5.0.20240423"
|
||||
types-pyyaml = "^6.0.12.20240311"
|
||||
pyarrow-stubs = "^10.0.1.7"
|
||||
pandas-stubs = "^2.2.2.240603"
|
||||
|
||||
[tool.poetry.group.powermon]
|
||||
optional = true
|
||||
@@ -67,6 +66,7 @@ ipywidgets = "^8.1.3"
|
||||
jupyterlab-widgets = "^3.0.11"
|
||||
|
||||
[tool.poetry.extras]
|
||||
cli = ["pyqrcode", "print-color", "dotmap", "argcomplete", "wcwidth"]
|
||||
tunnel = ["pytap2"]
|
||||
analysis = ["dash", "dash-bootstrap-components", "pandas", "pandas-stubs"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user