Compare commits

...

100 Commits
2.4.2 ... 2.5.3

Author SHA1 Message Date
github-actions
f08ec1885b bump version to 2.5.3 2024-10-18 17:02:53 +00:00
Ian McEwen
feca49faed Merge pull request #696 from fmoessbauer/master
fix base64 encoding of key field in config
2024-10-18 09:57:13 -07:00
Felix Moessbauer
dfaf1a275d fix base64 encoding of key field in config
The security.privateKey and security.publicKey fields are of type bytes,
but the protobuf MessageToDict converts them to base64 encoded strings.
When importing the config again, this is read as a string, which breaks
the import. Instead, the value needs to be prefixed with "base64:", so
the type handling logic on import kicks in and decodes the value to a
bytes array again.

Fixes: #678
2024-10-18 16:13:25 +02:00
Ian McEwen
da7fa31805 tweak documentation formatting 2024-10-16 20:52:10 -07:00
Ian McEwen
12fd29b203 Merge pull request #694 from ianmcorvidae/configure-fixed-position
Use dedicated fixed position admin message for --configure
2024-10-16 16:01:06 -07:00
Ian McEwen
a43dd201ba Merge pull request #695 from ianmcorvidae/ble-disconnect
Send the meshtastic.connection.lost message from BLEInterface's close method
2024-10-16 16:00:49 -07:00
Ian McEwen
a64a9d203a Send the meshtastic.connection.lost message from BLEInterface's close method 2024-10-16 12:13:30 -07:00
Ian McEwen
10136962d7 Use dedicated fixed position admin message for --configure 2024-10-15 07:28:55 -07:00
Ian McEwen
3afb294f9b Merge pull request #691 from logikal/telemetry_output
autoprint other types of telemetry when returned from --request-telemetry
2024-10-14 17:11:00 -07:00
Sean Kilgore
ee405fec41 autoprint other types of telemetry when returned from --request-telemetry 2024-10-14 16:58:52 -07:00
Ian McEwen
3eabaf91d0 Merge pull request #687 from ianmcorvidae/telemetry-types
Support requesting different telemetry types
2024-10-13 21:50:04 -07:00
Ian McEwen
78b92cecc9 fix type check 2024-10-13 20:40:22 -07:00
Ian McEwen
7088b90514 Support requesting different telemetry types 2024-10-13 20:35:11 -07:00
Ian McEwen
2ae81f8602 Merge pull request #686 from jose1711/typofix
Fix typo.
2024-10-13 18:00:16 -07:00
Jose Riha
923f5e82d0 Fix typo. 2024-10-14 02:48:41 +02:00
Ian McEwen
05731128fa missed a spot 2024-10-12 12:52:36 -07:00
Ian McEwen
0523d4c94f disable R0917 pylint failures 2024-10-12 12:49:14 -07:00
Ian McEwen
90e901de79 Upgrade bleak and therefore also the supported python versions 2024-10-12 12:32:43 -07:00
Ian McEwen
6606851135 Merge pull request #685 from ianmcorvidae/more-telemetry
Add other telemetry variants to automatic handling/adding to node information
2024-10-12 11:59:45 -07:00
Ian McEwen
33fecbd74d Add other telemetry variants to automatic handling/adding to node information 2024-10-12 11:56:55 -07:00
Ian McEwen
6b9db7abd9 2.5.3 setup 2024-10-12 09:33:28 -07:00
github-actions
ece6286d82 bump version to 2.5.2 2024-10-12 16:31:48 +00:00
Ian McEwen
0bb4b31b6a Merge pull request #679 from ianmcorvidae/argument-groups
Add a number of argument groups to organize the help output
2024-10-03 19:45:13 -07:00
Ian McEwen
915066e0af add metavars for a bunch of arguments for nicer docs 2024-10-03 19:45:03 -07:00
Ian McEwen
6be3969577 Add a number of argument groups to organize the help output 2024-10-01 18:10:14 -07:00
Ian McEwen
b73cc1f499 Make it so wantconfig isn't a 1 in 4294967296 lottery for getting no nodes 2024-10-01 14:00:06 -07:00
Ian McEwen
65305af184 protobufs/alpha version: 2.5.2 2024-09-29 14:34:53 -07:00
github-actions
3fb1e67357 bump version to 2.5.1 2024-09-29 21:30:36 +00:00
Ian McEwen
cbd3c119fe Fix pylint errors 2024-09-28 20:15:08 -07:00
Ian McEwen
bbd6d6a541 Change order of logging and parsing fromRadioBytes, and add a bit more traceback logging at that point 2024-09-28 20:11:52 -07:00
Ian McEwen
6e1217c7ca Merge pull request #677 from ianmcorvidae/pkiencrypted_admin
Default to pkiEncrypted always on for admin messages
2024-09-28 18:40:31 -07:00
Ian McEwen
81db38956b Silence pylint 2024-09-28 18:37:05 -07:00
Ian McEwen
27729995d2 Default to pkiEncrypted always on for admin messages 2024-09-28 11:13:04 -07:00
Ian McEwen
d875a574b6 Merge pull request #676 from ianmcorvidae/set-time
Add a --set-time command that set's the node time using a provided timestamp or the host system clock
2024-09-22 10:06:09 -07:00
Ian McEwen
40019a9712 Add a --set-time command that set's the node time using a provided timestamp or the host system clock. 2024-09-22 09:32:04 -07:00
Ian McEwen
de657bab24 Merge pull request #675 from djholt/feature/remote-config-position
Enable setting and removing fixed position via remote admin
2024-09-19 11:24:23 -07:00
DJ Holt
40353a387e Fix tests for remote position configs 2024-09-19 03:31:01 -06:00
DJ Holt
9949d144a1 Enable setting and removing fixed position via remote admin 2024-09-19 02:39:49 -06:00
Ian McEwen
48a06c6e1e protobufs & alpha version number: v2.5.1 2024-09-18 14:58:05 -07:00
Ian McEwen
c696d59b90 Set list-type keys differently, excluding 0-like values and resetting whole list 2024-09-17 21:52:57 -07:00
Ian McEwen
4fdbcb9679 Fix test_fuzz_fromStr for floats 2024-09-17 21:10:57 -07:00
Ian McEwen
5d6dfb877b Merge pull request #673 from djholt/feature/tcp-port
Allow port number to be specified with tcp hostname
2024-09-17 21:08:03 -07:00
Ian McEwen
951edfe27b Merge pull request #665 from lysol/remote-admin-retry
Retry admin channel setting retrieval and add configurable timeout
2024-09-17 21:06:38 -07:00
DJ Holt
5cc9627e21 Refactor default port number to variable 2024-09-16 23:41:44 -06:00
DJ Holt
bf904c6906 Allow port number to be specified with tcp hostname 2024-09-16 23:24:03 -06:00
Derek Arnold
2026212a00 please pylint with a docstring and newline 2024-09-15 16:27:40 -05:00
Derek Arnold
34f9be255e fix unrelated bug when fromStr input is short hex
For example, 0x0 will generate an unhandled ValueError. This was caught
during a random unit test run for 3.9, so I figure I'd fix it.

This is unrelated to the PR otherwise.
2024-09-15 16:20:50 -05:00
Derek Arnold
e561222ea7 add docstrings 2024-09-15 16:06:44 -05:00
Derek Arnold
73a1bbc7d5 add test coverage for changes to requestChannels 2024-09-15 16:02:59 -05:00
Derek Arnold
8f2c397fbf missed one reference for requestChannelRetries 🤡 2024-09-15 14:01:41 -05:00
Derek Arnold
62f5201a38 Add test covering retry logic 2024-09-15 12:04:22 -05:00
Derek Arnold
9e7d5e96ab Rename "retries" to "attempts"
Otherwise, semantically, it's off-by-one.
2024-09-15 12:03:51 -05:00
Derek Arnold
aa74db46cb update message check in test to reflect new message 2024-09-15 11:59:03 -05:00
Derek Arnold
1967519deb correct type issue during initial assignment 2024-09-15 11:52:27 -05:00
Derek Arnold
662aea049a Merge branch 'master' into remote-admin-retry 2024-09-15 11:46:32 -05:00
Derek Arnold
44cfd72a80 make sure new_index is always an int 2024-09-15 11:39:10 -05:00
Derek Arnold
abe1dd47ca add type to argument 2024-09-15 11:36:23 -05:00
Ian McEwen
584a14f578 Merge pull request #668 from ianmcorvidae/channel-preset-optimize
Change modem preset shortcuts to not request channels, and to request remote config when needed
2024-09-12 16:20:59 -07:00
github-actions
f7724295f9 bump version to 2.5.0 2024-09-12 16:27:45 +00:00
Ian McEwen
cc2067b729 clean up settings response to use CopyFrom to be better at repeated and nested fields 2024-09-11 17:10:04 -07:00
Ian McEwen
180ddbcd1a Merge pull request #672 from ianmcorvidae/detect-repeating
Detect repeating fields using field labels, enabling admin key to be set
2024-09-11 16:36:29 -07:00
Ian McEwen
3bbd02c915 Detect repeating fields using field labels, enabling admin key to be set 2024-09-11 16:34:03 -07:00
Ian McEwen
23e6eca056 Merge pull request #671 from ianmcorvidae/factory-reset-update
Split factory reset into two variants
2024-09-11 09:43:16 -07:00
Ian McEwen
21ff4a1a4a Split factory reset into two variants 2024-09-11 09:40:26 -07:00
Ian McEwen
ef6db0e48c Merge branch 'master' into 2.5 2024-09-11 09:21:01 -07:00
Ian McEwen
43b0993aaa Merge branch 'master' into 2.5 2024-09-11 09:19:43 -07:00
github-actions
9423a8a8b9 bump version to 2.4.3 2024-09-11 16:16:12 +00:00
Ian McEwen
33a13f715e 2.4.3 prep (protobufs, alpha version) 2024-09-11 09:12:41 -07:00
Ian McEwen
8ba92da7cf Change modem preset shortcuts to not request channels, and to request remote config when needed 2024-09-06 23:38:52 -07:00
Ian McEwen
0d26c26f7e update protobufs to master 2024-09-06 23:13:31 -07:00
Ian McEwen
399dd477b8 Merge branch 'master' into 2.5 2024-09-05 14:00:35 -07:00
Derek Arnold
3811226a61 add a configurable timeout 2024-09-03 22:12:03 -05:00
Derek Arnold
b6547c9737 actually link up the retry args from the commandline to getNode 2024-09-03 22:11:52 -05:00
Derek Arnold
9612aea9b9 Add in a retry mechanism for channel settings
Attempts multiple times to fetch things over the admin channel
before giving up.
2024-09-03 21:58:16 -05:00
Ian McEwen
4b60c5b457 Merge pull request #660 from GUVWAF/2way_traceroute
HopStart should be set for route back to be valid
2024-08-26 11:40:08 -07:00
GUVWAF
c92474cf36 HopStart should be set for route back to be valid 2024-08-26 20:32:51 +02:00
Ian McEwen
b2acc84717 remove trailing whitespace 2024-08-25 18:27:34 -07:00
Ian McEwen
1981f0e899 Merge pull request #654 from GUVWAF/2way_traceroute
Show two-way traceroute result with SNR if available
2024-08-25 16:54:36 -07:00
Ian McEwen
84dff75399 allow for underscore-only stuff in camel_to_snake, silly as that is 2024-08-24 23:38:48 -07:00
Ian McEwen
df12b8a659 appease the pylint beast 2024-08-24 23:34:28 -07:00
Ian McEwen
eedf42b904 add more fuzzing tests for utility functions 2024-08-24 22:25:18 -07:00
Ian McEwen
e7ed254d9d appease pylint, tests, mypy 2024-08-24 22:00:29 -07:00
Ian McEwen
dfa29bbb7c Add ensureSessionKey to setURL and setFixedPosition calls 2024-08-24 21:50:44 -07:00
Ian McEwen
5a06888cc7 Merge pull request #656 from meshtastic/more-admin
More admin
2024-08-24 21:48:19 -07:00
Jonathan Bennett
a9e2168f1d Refactor to add ensureSessionKey function 2024-08-24 20:18:57 -05:00
Jonathan Bennett
eec745c861 Add missed colon in if statement 2024-08-24 19:29:18 -05:00
Jonathan Bennett
4cc283d004 Add the admin sessionkey_only request 2024-08-24 17:27:42 -05:00
Ian McEwen
bc508ff9e6 cleanup admin stuff a little 2024-08-24 14:15:37 -07:00
Ian McEwen
ff72fc4804 Merge pull request #655 from meshtastic/show-pubkey
Adds admin session_passkey handling for 2.5 remote admin
2024-08-24 14:12:41 -07:00
Jonathan Bennett
78399503c5 Adds handlers to get and set admin session_key for remote admin 2024-08-24 15:32:44 -05:00
GUVWAF
216fd7ddc4 Show two-way traceroute result with SNR if available 2024-08-24 10:07:48 +02:00
Ian McEwen
688693d2fb Merge pull request #653 from meshtastic/show-pubkey
Adds handler function for public key, and adds to nodedb display
2024-08-23 20:41:40 -07:00
Jonathan Bennett
15b5e93563 Correctly format public key and add to node list 2024-08-23 22:21:54 -05:00
Ian McEwen
1bbcc452ae precalculate bit-shifts and don't generate too-large random numbers for packet ID generation 2024-08-23 15:34:25 -07:00
Ben Meadors
1abe00d0b2 Merge pull request #652 from ianmcorvidae/randomized-packet-ids
randomize packet IDs as firmware does
2024-08-23 17:30:07 -05:00
Ian McEwen
c8cf8094c3 randomize packet IDs as firmware does 2024-08-23 13:18:23 -07:00
Ian McEwen
477690edde mark protobufs folder as generated code for github 2024-08-21 22:27:18 -07:00
Ian McEwen
58466f2ab7 Add wiring for security config in node.py 2024-08-21 22:11:45 -07:00
Ian McEwen
bb6f51eb43 protobufs: 2.5 (in progress, untagged) 2024-08-21 21:58:56 -07:00
Ian McEwen
48987c38e2 set alpha version 2024-08-21 21:55:43 -07:00
37 changed files with 3573 additions and 2143 deletions

1
.gitattributes vendored
View File

@@ -2,3 +2,4 @@
*.{cmd,[cC][mM][dD]} text eol=crlf *.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf *.{bat,[bB][aA][tT]} text eol=crlf
*.{sh,[sS][hH]} text eol=lf *.{sh,[sS][hH]} text eol=lf
meshtastic/protobuf/* linguist-generated=true

View File

@@ -2,41 +2,44 @@
# A library for the Meshtastic Client API # A library for the Meshtastic Client API
Primary interfaces: SerialInterface, TCPInterface, BLEInterface Primary interfaces: SerialInterface, TCPInterface, BLEInterface
Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)" Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
Source code on [github](https://github.com/meshtastic/python) Source code on [github](https://github.com/meshtastic/python)
notable properties of interface classes: 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. node in the mesh. This is a read-only datastructure.
- nodesByNum - like "nodes" but keyed by nodeNum instead of nodeId - `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) - `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 - `localNode` - Pointer to a node object for the local node
notable properties of nodes: 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. - `localConfig` - Current radio settings, can be written to the radio with the `writeConfig` method.
- channels - The node's channels, keyed by index. - `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 # Published PubSub topics
We use a [publish-subscribe](https://pypubsub.readthedocs.io/en/v4.0.3/) model to communicate asynchronous events. Available We use a [publish-subscribe](https://pypubsub.readthedocs.io/en/v4.0.3/) model to communicate asynchronous events. Available
topics: topics:
- meshtastic.connection.established - published once we've successfully connected to the radio and downloaded the node DB - `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.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.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". 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.position(packet)`
- meshtastic.receive.user(packet) - `meshtastic.receive.user(packet)`
- meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum) - `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.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.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 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 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 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 `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. unicode scripts they can be different.
# Example Usage # Example Usage
@@ -194,13 +197,31 @@ def _onNodeInfoReceive(iface, asDict):
def _onTelemetryReceive(iface, asDict): def _onTelemetryReceive(iface, asDict):
"""Automatically update device metrics on received packets""" """Automatically update device metrics on received packets"""
logging.debug(f"in _onTelemetryReceive() asDict:{asDict}") logging.debug(f"in _onTelemetryReceive() asDict:{asDict}")
deviceMetrics = asDict.get("decoded", {}).get("telemetry", {}).get("deviceMetrics") if "from" not in asDict:
if "from" in asDict and deviceMetrics is not None: return
node = iface._getOrCreateByNum(asDict["from"])
newMetrics = node.get("deviceMetrics", {}) toUpdate = None
newMetrics.update(deviceMetrics)
logging.debug(f"updating metrics for {asDict['from']} to {newMetrics}") telemetry = asDict.get("decoded", {}).get("telemetry", {})
node["deviceMetrics"] = newMetrics 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): def _receiveInfoUpdate(iface, asDict):
if "from" in asDict: if "from" in asDict:
@@ -209,6 +230,12 @@ def _receiveInfoUpdate(iface, asDict):
iface._getOrCreateByNum(asDict["from"])["snr"] = asDict.get("rxSnr") iface._getOrCreateByNum(asDict["from"])["snr"] = asDict.get("rxSnr")
iface._getOrCreateByNum(asDict["from"])["hopLimit"] = asDict.get("hopLimit") 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""" """Well known message payloads can register decoders for automatic protobuf parsing"""
protocols = { protocols = {
@@ -228,7 +255,9 @@ protocols = {
portnums_pb2.PortNum.NODEINFO_APP: KnownProtocol( portnums_pb2.PortNum.NODEINFO_APP: KnownProtocol(
"user", mesh_pb2.User, _onNodeInfoReceive "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.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol( portnums_pb2.PortNum.TELEMETRY_APP: KnownProtocol(
"telemetry", telemetry_pb2.Telemetry, _onTelemetryReceive "telemetry", telemetry_pb2.Telemetry, _onTelemetryReceive

View File

File diff suppressed because it is too large Load Diff

View File

@@ -218,7 +218,7 @@ class BLEInterface(MeshInterface):
logging.error(f"Error closing mesh interface: {e}") logging.error(f"Error closing mesh interface: {e}")
if self._want_receive: 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: if self._receiveThread:
self._receiveThread.join( self._receiveThread.join(
timeout=2 timeout=2
@@ -230,6 +230,7 @@ class BLEInterface(MeshInterface):
self.client.disconnect() self.client.disconnect()
self.client.close() self.client.close()
self.client = None self.client = None
self._disconnected() # send the disconnected indicator up to clients
class BLEClient: class BLEClient:

View File

@@ -1,5 +1,6 @@
"""Mesh Interface class """Mesh Interface class
""" """
# pylint: disable=R0917
import collections import collections
import json import json
@@ -8,6 +9,7 @@ import random
import sys import sys
import threading import threading
import time import time
import traceback
from datetime import datetime from datetime import datetime
from decimal import Decimal from decimal import Decimal
from typing import Any, Callable, Dict, List, Optional, Union from typing import Any, Callable, Dict, List, Optional, Union
@@ -139,13 +141,13 @@ class MeshInterface: # pylint: disable=R0902
def __enter__(self): def __enter__(self):
return 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: if exc_type is not None and exc_value is not None:
logging.error( logging.error(
f"An exception of type {exc_type} with value {exc_value} has occurred" f"An exception of type {exc_type} with value {exc_value} has occurred"
) )
if traceback is not None: if trace is not None:
logging.error(f"Traceback: {traceback}") logging.error(f"Traceback: {trace}")
self.close() self.close()
@staticmethod @staticmethod
@@ -260,6 +262,7 @@ class MeshInterface: # pylint: disable=R0902
"AKA": user.get("shortName", "N/A"), "AKA": user.get("shortName", "N/A"),
"ID": user["id"], "ID": user["id"],
"Hardware": user.get("hwModel", "UNSET"), "Hardware": user.get("hwModel", "UNSET"),
"Pubkey": user.get("publicKey", "UNSET"),
} }
) )
@@ -314,19 +317,33 @@ class MeshInterface: # pylint: disable=R0902
return table return table
def getNode( def getNode(
self, nodeId: str, requestChannels: bool = True self, nodeId: str, requestChannels: bool = True, requestChannelAttempts: int = 3, timeout: int = 300
) -> meshtastic.node.Node: ) -> meshtastic.node.Node:
"""Return a node object which contains device settings and channel info""" """Return a node object which contains device settings and channel info"""
if nodeId in (LOCAL_ADDR, BROADCAST_ADDR): if nodeId in (LOCAL_ADDR, BROADCAST_ADDR):
return self.localNode return self.localNode
else: else:
n = meshtastic.node.Node(self, nodeId) n = meshtastic.node.Node(self, nodeId, timeout=timeout)
# Only request device settings and channel info when necessary # Only request device settings and channel info when necessary
if requestChannels: if requestChannels:
logging.debug("About to requestChannels") logging.debug("About to requestChannels")
n.requestChannels() n.requestChannels()
if not n.waitForConfig(): retries_left = requestChannelAttempts
our_exit("Error: Timed out waiting for channels") 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(f"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 return n
def sendText( def sendText(
@@ -379,7 +396,9 @@ class MeshInterface: # pylint: disable=R0902
onResponseAckPermitted: bool=False, onResponseAckPermitted: bool=False,
channelIndex: int=0, channelIndex: int=0,
hopLimit: Optional[int]=None, hopLimit: Optional[int]=None,
): pkiEncrypted: Optional[bool]=False,
publicKey: Optional[bytes]=None,
): # pylint: disable=R0913
"""Send a data packet to some other node """Send a data packet to some other node
Keyword Arguments: Keyword Arguments:
@@ -434,7 +453,7 @@ class MeshInterface: # pylint: disable=R0902
if onResponse is not None: if onResponse is not None:
logging.debug(f"Setting a response handler for requestId {meshPacket.id}") logging.debug(f"Setting a response handler for requestId {meshPacket.id}")
self._addResponseHandler(meshPacket.id, onResponse, ackPermitted=onResponseAckPermitted) 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 return p
def sendPosition( def sendPosition(
@@ -539,17 +558,46 @@ class MeshInterface: # pylint: disable=R0902
def onResponseTraceRoute(self, p: dict): def onResponseTraceRoute(self, p: dict):
"""on response for trace route""" """on response for trace route"""
UNK_SNR = -128 # Value representing unknown SNR
routeDiscovery = mesh_pb2.RouteDiscovery() routeDiscovery = mesh_pb2.RouteDiscovery()
routeDiscovery.ParseFromString(p["decoded"]["payload"]) routeDiscovery.ParseFromString(p["decoded"]["payload"])
asDict = google.protobuf.json_format.MessageToDict(routeDiscovery) asDict = google.protobuf.json_format.MessageToDict(routeDiscovery)
print("Route traced:") print("Route traced towards destination:")
routeStr = self._nodeNumToId(p["to"]) or f"{p['to']:08x}" routeStr = self._nodeNumToId(p["to"], False) or f"{p['to']:08x}" # Start with destination of response
if "route" in asDict:
for nodeNum in asDict["route"]: # SNR list should have one more entry than the route, as the final destination adds its SNR also
routeStr += " --> " + (self._nodeNumToId(nodeNum) or f"{nodeNum:08x}") lenTowards = 0 if "route" not in asDict else len(asDict["route"])
routeStr += " --> " + (self._nodeNumToId(p["from"]) or f"{p['from']:08x}") snrTowardsValid = "snrTowards" in asDict and len(asDict["snrTowards"]) == lenTowards + 1
print(routeStr) 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 self._acknowledgment.receivedTraceRoute = True
@@ -558,32 +606,38 @@ class MeshInterface: # pylint: disable=R0902
destinationId: Union[int, str] = BROADCAST_ADDR, destinationId: Union[int, str] = BROADCAST_ADDR,
wantResponse: bool = False, wantResponse: bool = False,
channelIndex: int = 0, channelIndex: int = 0,
telemetryType: str = "device_metrics"
): ):
"""Send telemetry and optionally ask for a response""" """Send telemetry and optionally ask for a response"""
r = telemetry_pb2.Telemetry() r = telemetry_pb2.Telemetry()
if self.nodes is not None: if telemetryType == "environment_metrics":
node = next( r.environment_metrics.CopyFrom(telemetry_pb2.EnvironmentMetrics())
n for n in self.nodes.values() if n["num"] == self.localNode.nodeNum elif telemetryType == "air_quality_metrics":
) r.air_quality_metrics.CopyFrom(telemetry_pb2.AirQualityMetrics())
if node is not None: elif telemetryType == "power_metrics":
metrics = node.get("deviceMetrics") r.power_metrics.CopyFrom(telemetry_pb2.PowerMetrics())
if metrics: else: # fall through to device metrics
batteryLevel = metrics.get("batteryLevel") if self.nodesByNum is not None:
if batteryLevel is not None: node = self.nodesByNum.get(self.localNode.nodeNum)
r.device_metrics.battery_level = batteryLevel if node is not None:
voltage = metrics.get("voltage") metrics = node.get("deviceMetrics")
if voltage is not None: if metrics:
r.device_metrics.voltage = voltage batteryLevel = metrics.get("batteryLevel")
channel_utilization = metrics.get("channelUtilization") if batteryLevel is not None:
if channel_utilization is not None: r.device_metrics.battery_level = batteryLevel
r.device_metrics.channel_utilization = channel_utilization voltage = metrics.get("voltage")
air_util_tx = metrics.get("airUtilTx") if voltage is not None:
if air_util_tx is not None: r.device_metrics.voltage = voltage
r.device_metrics.air_util_tx = air_util_tx channel_utilization = metrics.get("channelUtilization")
uptime_seconds = metrics.get("uptimeSeconds") if channel_utilization is not None:
if uptime_seconds is not None: r.device_metrics.channel_utilization = channel_utilization
r.device_metrics.uptime_seconds = uptime_seconds 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: if wantResponse:
onResponse = self.onResponseTelemetry onResponse = self.onResponseTelemetry
@@ -607,22 +661,32 @@ class MeshInterface: # pylint: disable=R0902
self._acknowledgment.receivedTelemetry = True self._acknowledgment.receivedTelemetry = True
telemetry = telemetry_pb2.Telemetry() telemetry = telemetry_pb2.Telemetry()
telemetry.ParseFromString(p["decoded"]["payload"]) telemetry.ParseFromString(p["decoded"]["payload"])
print("Telemetry received:") print("Telemetry received:")
if telemetry.device_metrics.battery_level is not None: # Check if the telemetry message has the device_metrics field
print(f"Battery level: {telemetry.device_metrics.battery_level:.2f}%") # This is the original code that was the default for --request-telemetry and is kept for compatibility
if telemetry.device_metrics.voltage is not None: if telemetry.HasField("device_metrics"):
print(f"Voltage: {telemetry.device_metrics.voltage:.2f} V") if telemetry.device_metrics.battery_level is not None:
if telemetry.device_metrics.channel_utilization is not None: print(f"Battery level: {telemetry.device_metrics.battery_level:.2f}%")
print( if telemetry.device_metrics.voltage is not None:
f"Total channel utilization: {telemetry.device_metrics.channel_utilization:.2f}%" print(f"Voltage: {telemetry.device_metrics.voltage:.2f} V")
) if telemetry.device_metrics.channel_utilization is not None:
if telemetry.device_metrics.air_util_tx is not None: print(
print( f"Total channel utilization: {telemetry.device_metrics.channel_utilization:.2f}%"
f"Transmit air utilization: {telemetry.device_metrics.air_util_tx:.2f}%" )
) if telemetry.device_metrics.air_util_tx is not None:
if telemetry.device_metrics.uptime_seconds is not None: print(
print(f"Uptime: {telemetry.device_metrics.uptime_seconds} s") 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": elif p["decoded"]["portnum"] == "ROUTING_APP":
if p["decoded"]["routing"]["errorReason"] == "NO_RESPONSE": if p["decoded"]["routing"]["errorReason"] == "NO_RESPONSE":
@@ -645,7 +709,9 @@ class MeshInterface: # pylint: disable=R0902
meshPacket: mesh_pb2.MeshPacket, meshPacket: mesh_pb2.MeshPacket,
destinationId: Union[int,str]=BROADCAST_ADDR, destinationId: Union[int,str]=BROADCAST_ADDR,
wantAck: bool=False, 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). """Send a MeshPacket to the specified node (or if unspecified, broadcast).
You probably don't want this - use sendData instead. You probably don't want this - use sendData instead.
@@ -694,6 +760,12 @@ class MeshInterface: # pylint: disable=R0902
loraConfig = getattr(self.localNode.localConfig, "lora") loraConfig = getattr(self.localNode.localConfig, "lora")
meshPacket.hop_limit = getattr(loraConfig, "hop_limit") 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), # 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. # we should pick a new unique ID so the message can be tracked.
if meshPacket.id == 0: if meshPacket.id == 0:
@@ -774,6 +846,13 @@ class MeshInterface: # pylint: disable=R0902
return user.get("shortName", None) return user.get("shortName", None)
return 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): def _waitConnected(self, timeout=30.0):
"""Block until the initial node db download is complete, or timeout """Block until the initial node db download is complete, or timeout
and raise an exception""" and raise an exception"""
@@ -794,7 +873,10 @@ class MeshInterface: # pylint: disable=R0902
"Not connected yet, can not generate packet" "Not connected yet, can not generate packet"
) )
else: 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 return self.currentPacketId
def _disconnected(self): def _disconnected(self):
@@ -849,6 +931,8 @@ class MeshInterface: # pylint: disable=R0902
startConfig = mesh_pb2.ToRadio() startConfig = mesh_pb2.ToRadio()
if self.configId is None or not self.noNodes: if self.configId is None or not self.noNodes:
self.configId = random.randint(0, 0xFFFFFFFF) self.configId = random.randint(0, 0xFFFFFFFF)
if self.configId == NODELESS_WANT_CONFIG_ID:
self.configId = self.configId + 1
startConfig.want_config_id = self.configId startConfig.want_config_id = self.configId
self._sendToRadio(startConfig) self._sendToRadio(startConfig)
@@ -959,10 +1043,17 @@ class MeshInterface: # pylint: disable=R0902
Called by subclasses.""" Called by subclasses."""
fromRadio = mesh_pb2.FromRadio() fromRadio = mesh_pb2.FromRadio()
fromRadio.ParseFromString(fromRadioBytes)
logging.debug( logging.debug(
f"in mesh_interface.py _handleFromRadio() fromRadioBytes: {fromRadioBytes}" 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) asDict = google.protobuf.json_format.MessageToDict(fromRadio)
logging.debug(f"Received from radio: {fromRadio}") logging.debug(f"Received from radio: {fromRadio}")
if fromRadio.HasField("my_info"): if fromRadio.HasField("my_info"):
@@ -1051,7 +1142,10 @@ class MeshInterface: # pylint: disable=R0902
self.localNode.localConfig.bluetooth.CopyFrom( self.localNode.localConfig.bluetooth.CopyFrom(
fromRadio.config.bluetooth fromRadio.config.bluetooth
) )
elif fromRadio.config.HasField("security"):
self.localNode.localConfig.security.CopyFrom(
fromRadio.config.security
)
elif fromRadio.moduleConfig.HasField("mqtt"): elif fromRadio.moduleConfig.HasField("mqtt"):
self.localNode.moduleConfig.mqtt.CopyFrom(fromRadio.moduleConfig.mqtt) self.localNode.moduleConfig.mqtt.CopyFrom(fromRadio.moduleConfig.mqtt)
elif fromRadio.moduleConfig.HasField("serial"): elif fromRadio.moduleConfig.HasField("serial"):
@@ -1117,17 +1211,21 @@ class MeshInterface: # pylint: disable=R0902
position["longitude"] = float(position["longitudeI"] * Decimal("1e-7")) position["longitude"] = float(position["longitudeI"] * Decimal("1e-7"))
return position 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 """Map a node node number to a node ID
Arguments: Arguments:
num {int} -- Node number num {int} -- Node number
isDest {bool} -- True if the node number is a destination (to show broadcast address or unknown node)
Returns: Returns:
string -- Node ID string -- Node ID
""" """
if num == BROADCAST_NUM: if num == BROADCAST_NUM:
return BROADCAST_ADDR if isDest:
return BROADCAST_ADDR
else:
return "Unknown"
try: try:
return self.nodesByNum[num]["user"]["id"] # type: ignore[index] return self.nodesByNum[num]["user"]["id"] # type: ignore[index]
@@ -1200,7 +1298,7 @@ class MeshInterface: # pylint: disable=R0902
# /add fromId and toId fields based on the node ID # /add fromId and toId fields based on the node ID
try: try:
asDict["fromId"] = self._nodeNumToId(asDict["from"]) asDict["fromId"] = self._nodeNumToId(asDict["from"], False)
except Exception as ex: except Exception as ex:
logging.warning(f"Not populating fromId {ex}") logging.warning(f"Not populating fromId {ex}")
try: try:

View File

@@ -5,7 +5,7 @@ import base64
import logging import logging
import time 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.protobuf import admin_pb2, apponly_pb2, channel_pb2, localonly_pb2, mesh_pb2, portnums_pb2
from meshtastic.util import ( from meshtastic.util import (
@@ -25,15 +25,15 @@ class Node:
Includes methods for localConfig, moduleConfig and channels 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""" """Constructor"""
self.iface = iface self.iface = iface
self.nodeNum = nodeNum self.nodeNum = nodeNum
self.localConfig = localonly_pb2.LocalConfig() self.localConfig = localonly_pb2.LocalConfig()
self.moduleConfig = localonly_pb2.LocalModuleConfig() self.moduleConfig = localonly_pb2.LocalModuleConfig()
self.channels = None self.channels = None
self._timeout = Timeout(maxSecs=300) self._timeout = Timeout(maxSecs=timeout)
self.partialChannels = None self.partialChannels: Optional[List] = None
self.noProto = noProto self.noProto = noProto
self.cannedPluginMessage = None self.cannedPluginMessage = None
self.cannedPluginMessageMessages = None self.cannedPluginMessageMessages = None
@@ -77,17 +77,19 @@ class Node:
self.channels = channels self.channels = channels
self._fixupChannels() self._fixupChannels()
def requestChannels(self): def requestChannels(self, startingIndex: int = 0):
"""Send regular MeshPackets to ask channels.""" """Send regular MeshPackets to ask channels."""
logging.debug(f"requestChannels for nodeNum:{self.nodeNum}") logging.debug(f"requestChannels for nodeNum:{self.nodeNum}")
self.channels = None # only initialize if we're starting out fresh
self.partialChannels = [] # We keep our channels in a temp array until finished if startingIndex == 0:
self.channels = None
self._requestChannel(0) self.partialChannels = [] # We keep our channels in a temp array until finished
self._requestChannel(startingIndex)
def onResponseRequestSettings(self, p): def onResponseRequestSettings(self, p):
"""Handle the response packets for requesting settings _requestSettings()""" """Handle the response packets for requesting settings _requestSettings()"""
logging.debug(f"onResponseRequestSetting() p:{p}") logging.debug(f"onResponseRequestSetting() p:{p}")
config_values = None
if "routing" in p["decoded"]: if "routing" in p["decoded"]:
if p["decoded"]["routing"]["errorReason"] != "NONE": if p["decoded"]["routing"]["errorReason"] != "NONE":
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}') print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
@@ -97,13 +99,16 @@ class Node:
print("") print("")
adminMessage = p["decoded"]["admin"] adminMessage = p["decoded"]["admin"]
if "getConfigResponse" in adminMessage: if "getConfigResponse" in adminMessage:
oneof = "get_config_response"
resp = adminMessage["getConfigResponse"] resp = adminMessage["getConfigResponse"]
field = list(resp.keys())[0] field = list(resp.keys())[0]
config_type = self.localConfig.DESCRIPTOR.fields_by_name.get( config_type = self.localConfig.DESCRIPTOR.fields_by_name.get(
camel_to_snake(field) 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: elif "getModuleConfigResponse" in adminMessage:
oneof = "get_module_config_response"
resp = adminMessage["getModuleConfigResponse"] resp = adminMessage["getModuleConfigResponse"]
field = list(resp.keys())[0] field = list(resp.keys())[0]
config_type = self.moduleConfig.DESCRIPTOR.fields_by_name.get( 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'." "Did not receive a valid response. Make sure to have a shared channel named 'admin'."
) )
return return
for key, value in resp[field].items(): if config_values is not None:
setattr(config_values, camel_to_snake(key), value) raw_config = getattr(getattr(adminMessage['raw'], oneof), field)
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}") config_values.CopyFrom(raw_config)
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}")
def requestConfig(self, configType): def requestConfig(self, configType):
"""Request the config from the node via admin message""" """Request the config from the node via admin message"""
@@ -126,16 +132,18 @@ class Node:
else: else:
onResponse = self.onResponseRequestSettings onResponse = self.onResponseRequestSettings
print("Requesting current config from remote node (this can take a while).") 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: else:
p = admin_pb2.AdminMessage() msgIndex = configType.index
p.get_module_config_request = msgIndex if configType.containing_type.name == "LocalConfig":
self._sendAdmin(p, wantResponse=True, onResponse=onResponse) p.get_config_request = msgIndex
else:
p.get_module_config_request = msgIndex
self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
if onResponse: if onResponse:
self.iface.waitForAckNak() self.iface.waitForAckNak()
@@ -170,6 +178,8 @@ class Node:
p.set_config.lora.CopyFrom(self.localConfig.lora) p.set_config.lora.CopyFrom(self.localConfig.lora)
elif config_name == "bluetooth": elif config_name == "bluetooth":
p.set_config.bluetooth.CopyFrom(self.localConfig.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": elif config_name == "mqtt":
p.set_module_config.mqtt.CopyFrom(self.moduleConfig.mqtt) p.set_module_config.mqtt.CopyFrom(self.moduleConfig.mqtt)
elif config_name == "serial": elif config_name == "serial":
@@ -214,7 +224,7 @@ class Node:
def writeChannel(self, channelIndex, adminIndex=0): def writeChannel(self, channelIndex, adminIndex=0):
"""Write the current (edited) channel to the device""" """Write the current (edited) channel to the device"""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.set_channel.CopyFrom(self.channels[channelIndex]) p.set_channel.CopyFrom(self.channels[channelIndex])
self._sendAdmin(p, adminIndex=adminIndex) 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): def setOwner(self, long_name: Optional[str]=None, short_name: Optional[str]=None, is_licensed: bool=False):
"""Set device owner name""" """Set device owner name"""
logging.debug(f"in setOwner nodeNum:{self.nodeNum}") logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
nChars = 4 nChars = 4
@@ -367,6 +378,7 @@ class Node:
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.set_config.lora.CopyFrom(channelSet.lora_config) p.set_config.lora.CopyFrom(channelSet.lora_config)
self.ensureSessionKey()
self._sendAdmin(p) self._sendAdmin(p)
def onResponseRequestRingtone(self, p): def onResponseRequestRingtone(self, p):
@@ -415,7 +427,7 @@ class Node:
if len(ringtone) > 230: if len(ringtone) > 230:
our_exit("Warning: The ringtone must be less than 230 characters.") our_exit("Warning: The ringtone must be less than 230 characters.")
self.ensureSessionKey()
# split into chunks # split into chunks
chunks = [] chunks = []
chunks_size = 230 chunks_size = 230
@@ -491,7 +503,7 @@ class Node:
if len(message) > 200: if len(message) > 200:
our_exit("Warning: The canned message must be less than 200 characters.") our_exit("Warning: The canned message must be less than 200 characters.")
self.ensureSessionKey()
# split into chunks # split into chunks
chunks = [] chunks = []
chunks_size = 200 chunks_size = 200
@@ -518,6 +530,7 @@ class Node:
def exitSimulator(self): def exitSimulator(self):
"""Tell a simulator node to exit (this message """Tell a simulator node to exit (this message
is ignored for other nodes)""" is ignored for other nodes)"""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.exit_simulator = True p.exit_simulator = True
logging.debug("in exitSimulator()") logging.debug("in exitSimulator()")
@@ -526,6 +539,7 @@ class Node:
def reboot(self, secs: int = 10): def reboot(self, secs: int = 10):
"""Tell the node to reboot.""" """Tell the node to reboot."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.reboot_seconds = secs p.reboot_seconds = secs
logging.info(f"Telling node to reboot in {secs} seconds") logging.info(f"Telling node to reboot in {secs} seconds")
@@ -539,6 +553,7 @@ class Node:
def beginSettingsTransaction(self): def beginSettingsTransaction(self):
"""Tell the node to open a transaction to edit settings.""" """Tell the node to open a transaction to edit settings."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.begin_edit_settings = True p.begin_edit_settings = True
logging.info(f"Telling open a transaction to edit settings") logging.info(f"Telling open a transaction to edit settings")
@@ -552,6 +567,7 @@ class Node:
def commitSettingsTransaction(self): def commitSettingsTransaction(self):
"""Tell the node to commit the open transaction for editing settings.""" """Tell the node to commit the open transaction for editing settings."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.commit_edit_settings = True p.commit_edit_settings = True
logging.info(f"Telling node to commit open transaction for editing settings") logging.info(f"Telling node to commit open transaction for editing settings")
@@ -565,6 +581,7 @@ class Node:
def rebootOTA(self, secs: int = 10): def rebootOTA(self, secs: int = 10):
"""Tell the node to reboot into factory firmware.""" """Tell the node to reboot into factory firmware."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.reboot_ota_seconds = secs p.reboot_ota_seconds = secs
logging.info(f"Telling node to reboot to OTA in {secs} seconds") logging.info(f"Telling node to reboot to OTA in {secs} seconds")
@@ -578,6 +595,7 @@ class Node:
def enterDFUMode(self): def enterDFUMode(self):
"""Tell the node to enter DFU mode (NRF52).""" """Tell the node to enter DFU mode (NRF52)."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.enter_dfu_mode_request = True p.enter_dfu_mode_request = True
logging.info(f"Telling node to enable DFU mode") logging.info(f"Telling node to enable DFU mode")
@@ -591,6 +609,7 @@ class Node:
def shutdown(self, secs: int = 10): def shutdown(self, secs: int = 10):
"""Tell the node to shutdown.""" """Tell the node to shutdown."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.shutdown_seconds = secs p.shutdown_seconds = secs
logging.info(f"Telling node to shutdown in {secs} seconds") logging.info(f"Telling node to shutdown in {secs} seconds")
@@ -613,11 +632,16 @@ class Node:
) )
self.iface.waitForAckNak() self.iface.waitForAckNak()
def factoryReset(self): def factoryReset(self, full: bool = False):
"""Tell the node to factory reset.""" """Tell the node to factory reset."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.factory_reset = True if full:
logging.info(f"Telling node to factory reset") 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 sending to a remote node, wait for ACK/NAK
if self == self.iface.localNode: if self == self.iface.localNode:
@@ -628,6 +652,7 @@ class Node:
def removeNode(self, nodeId: Union[int, str]): def removeNode(self, nodeId: Union[int, str]):
"""Tell the node to remove a specific node by ID""" """Tell the node to remove a specific node by ID"""
self.ensureSessionKey()
if isinstance(nodeId, str): if isinstance(nodeId, str):
if nodeId.startswith("!"): if nodeId.startswith("!"):
nodeId = int(nodeId[1:], 16) nodeId = int(nodeId[1:], 16)
@@ -645,6 +670,7 @@ class Node:
def resetNodeDb(self): def resetNodeDb(self):
"""Tell the node to reset its list of nodes.""" """Tell the node to reset its list of nodes."""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.nodedb_reset = True p.nodedb_reset = True
logging.info(f"Telling node to reset the NodeDB") logging.info(f"Telling node to reset the NodeDB")
@@ -658,9 +684,7 @@ class Node:
def setFixedPosition(self, lat: Union[int, float], lon: Union[int, float], alt: int): 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""" """Tell the node to set fixed position to the provided value and enable the fixed position setting"""
if self != self.iface.localNode: self.ensureSessionKey()
logging.error("Setting position of remote nodes is not supported.")
return None
p = mesh_pb2.Position() p = mesh_pb2.Position()
if isinstance(lat, float) and lat != 0.0: if isinstance(lat, float) and lat != 0.0:
@@ -678,15 +702,40 @@ class Node:
a = admin_pb2.AdminMessage() a = admin_pb2.AdminMessage()
a.set_fixed_position.CopyFrom(p) 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): def removeFixedPosition(self):
"""Tell the node to remove the fixed position and set the fixed position setting to false""" """Tell the node to remove the fixed position and set the fixed position setting to false"""
self.ensureSessionKey()
p = admin_pb2.AdminMessage() p = admin_pb2.AdminMessage()
p.remove_fixed_position = True p.remove_fixed_position = True
logging.info(f"Telling node to remove fixed position") 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): def _fixupChannels(self):
"""Fixup indexes and add disabled channels as needed""" """Fixup indexes and add disabled channels as needed"""
@@ -831,7 +880,12 @@ class Node:
): # unless a special channel index was used, we want to use the admin index ): # unless a special channel index was used, we want to use the admin index
adminIndex = self.iface.localNode._getAdminChannelIndex() adminIndex = self.iface.localNode._getAdminChannelIndex()
logging.debug(f"adminIndex:{adminIndex}") 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( return self.iface.sendData(
p, p,
self.nodeNum, self.nodeNum,
@@ -840,4 +894,19 @@ class Node:
wantResponse=wantResponse, wantResponse=wantResponse,
onResponse=onResponse, onResponse=onResponse,
channelIndex=adminIndex, 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)

View File

@@ -18,7 +18,7 @@ from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb
from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2 from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/admin.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a+meshtastic/protobuf/connection_status.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xea\x12\n\x0c\x41\x64minMessage\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12<\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12\x37\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12J\n\x12get_config_request\x18\x05 \x01(\x0e\x32,.meshtastic.protobuf.AdminMessage.ConfigTypeH\x00\x12:\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12W\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.AdminMessage.ModuleConfigTypeH\x00\x12G\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32!.meshtastic.protobuf.ModuleConfigH\x00\x12\x34\n*get_canned_message_module_messages_request\x18\n \x01(\x08H\x00\x12\x35\n+get_canned_message_module_messages_response\x18\x0b \x01(\tH\x00\x12%\n\x1bget_device_metadata_request\x18\x0c \x01(\x08H\x00\x12K\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32#.meshtastic.protobuf.DeviceMetadataH\x00\x12\x1e\n\x14get_ringtone_request\x18\x0e \x01(\x08H\x00\x12\x1f\n\x15get_ringtone_response\x18\x0f \x01(\tH\x00\x12.\n$get_device_connection_status_request\x18\x10 \x01(\x08H\x00\x12\\\n%get_device_connection_status_response\x18\x11 \x01(\x0b\x32+.meshtastic.protobuf.DeviceConnectionStatusH\x00\x12:\n\x0cset_ham_mode\x18\x12 \x01(\x0b\x32\".meshtastic.protobuf.HamParametersH\x00\x12/\n%get_node_remote_hardware_pins_request\x18\x13 \x01(\x08H\x00\x12\x65\n&get_node_remote_hardware_pins_response\x18\x14 \x01(\x0b\x32\x33.meshtastic.protobuf.NodeRemoteHardwarePinsResponseH\x00\x12 \n\x16\x65nter_dfu_mode_request\x18\x15 \x01(\x08H\x00\x12\x1d\n\x13\x64\x65lete_file_request\x18\x16 \x01(\tH\x00\x12\x13\n\tset_scale\x18\x17 \x01(\rH\x00\x12.\n\tset_owner\x18 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12\x33\n\x0bset_channel\x18! \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x31\n\nset_config\x18\" \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12>\n\x11set_module_config\x18# \x01(\x0b\x32!.meshtastic.protobuf.ModuleConfigH\x00\x12,\n\"set_canned_message_module_messages\x18$ \x01(\tH\x00\x12\x1e\n\x14set_ringtone_message\x18% \x01(\tH\x00\x12\x1b\n\x11remove_by_nodenum\x18& \x01(\rH\x00\x12\x1b\n\x11set_favorite_node\x18\' \x01(\rH\x00\x12\x1e\n\x14remove_favorite_node\x18( \x01(\rH\x00\x12;\n\x12set_fixed_position\x18) \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x00\x12\x1f\n\x15remove_fixed_position\x18* \x01(\x08H\x00\x12\x1d\n\x13\x62\x65gin_edit_settings\x18@ \x01(\x08H\x00\x12\x1e\n\x14\x63ommit_edit_settings\x18\x41 \x01(\x08H\x00\x12\x1c\n\x12reboot_ota_seconds\x18_ \x01(\x05H\x00\x12\x18\n\x0e\x65xit_simulator\x18` \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18\x61 \x01(\x05H\x00\x12\x1a\n\x10shutdown_seconds\x18\x62 \x01(\x05H\x00\x12\x17\n\rfactory_reset\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x05H\x00\"\x95\x01\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x12\n\x0eNETWORK_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\x12\x14\n\x10\x42LUETOOTH_CONFIG\x10\x06\"\xbb\x02\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x12\x10\n\x0c\x41UDIO_CONFIG\x10\x07\x12\x19\n\x15REMOTEHARDWARE_CONFIG\x10\x08\x12\x17\n\x13NEIGHBORINFO_CONFIG\x10\t\x12\x1a\n\x16\x41MBIENTLIGHTING_CONFIG\x10\n\x12\x1a\n\x16\x44\x45TECTIONSENSOR_CONFIG\x10\x0b\x12\x15\n\x11PAXCOUNTER_CONFIG\x10\x0c\x42\x11\n\x0fpayload_variant\"[\n\rHamParameters\x12\x11\n\tcall_sign\x18\x01 \x01(\t\x12\x10\n\x08tx_power\x18\x02 \x01(\x05\x12\x11\n\tfrequency\x18\x03 \x01(\x02\x12\x12\n\nshort_name\x18\x04 \x01(\t\"o\n\x1eNodeRemoteHardwarePinsResponse\x12M\n\x19node_remote_hardware_pins\x18\x01 \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePinB`\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/admin.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a+meshtastic/protobuf/connection_status.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xef\x13\n\x0c\x41\x64minMessage\x12\x17\n\x0fsession_passkey\x18\x65 \x01(\x0c\x12\x1d\n\x13get_channel_request\x18\x01 \x01(\rH\x00\x12<\n\x14get_channel_response\x18\x02 \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x03 \x01(\x08H\x00\x12\x37\n\x12get_owner_response\x18\x04 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12J\n\x12get_config_request\x18\x05 \x01(\x0e\x32,.meshtastic.protobuf.AdminMessage.ConfigTypeH\x00\x12:\n\x13get_config_response\x18\x06 \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12W\n\x19get_module_config_request\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.AdminMessage.ModuleConfigTypeH\x00\x12G\n\x1aget_module_config_response\x18\x08 \x01(\x0b\x32!.meshtastic.protobuf.ModuleConfigH\x00\x12\x34\n*get_canned_message_module_messages_request\x18\n \x01(\x08H\x00\x12\x35\n+get_canned_message_module_messages_response\x18\x0b \x01(\tH\x00\x12%\n\x1bget_device_metadata_request\x18\x0c \x01(\x08H\x00\x12K\n\x1cget_device_metadata_response\x18\r \x01(\x0b\x32#.meshtastic.protobuf.DeviceMetadataH\x00\x12\x1e\n\x14get_ringtone_request\x18\x0e \x01(\x08H\x00\x12\x1f\n\x15get_ringtone_response\x18\x0f \x01(\tH\x00\x12.\n$get_device_connection_status_request\x18\x10 \x01(\x08H\x00\x12\\\n%get_device_connection_status_response\x18\x11 \x01(\x0b\x32+.meshtastic.protobuf.DeviceConnectionStatusH\x00\x12:\n\x0cset_ham_mode\x18\x12 \x01(\x0b\x32\".meshtastic.protobuf.HamParametersH\x00\x12/\n%get_node_remote_hardware_pins_request\x18\x13 \x01(\x08H\x00\x12\x65\n&get_node_remote_hardware_pins_response\x18\x14 \x01(\x0b\x32\x33.meshtastic.protobuf.NodeRemoteHardwarePinsResponseH\x00\x12 \n\x16\x65nter_dfu_mode_request\x18\x15 \x01(\x08H\x00\x12\x1d\n\x13\x64\x65lete_file_request\x18\x16 \x01(\tH\x00\x12\x13\n\tset_scale\x18\x17 \x01(\rH\x00\x12.\n\tset_owner\x18 \x01(\x0b\x32\x19.meshtastic.protobuf.UserH\x00\x12\x33\n\x0bset_channel\x18! \x01(\x0b\x32\x1c.meshtastic.protobuf.ChannelH\x00\x12\x31\n\nset_config\x18\" \x01(\x0b\x32\x1b.meshtastic.protobuf.ConfigH\x00\x12>\n\x11set_module_config\x18# \x01(\x0b\x32!.meshtastic.protobuf.ModuleConfigH\x00\x12,\n\"set_canned_message_module_messages\x18$ \x01(\tH\x00\x12\x1e\n\x14set_ringtone_message\x18% \x01(\tH\x00\x12\x1b\n\x11remove_by_nodenum\x18& \x01(\rH\x00\x12\x1b\n\x11set_favorite_node\x18\' \x01(\rH\x00\x12\x1e\n\x14remove_favorite_node\x18( \x01(\rH\x00\x12;\n\x12set_fixed_position\x18) \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x00\x12\x1f\n\x15remove_fixed_position\x18* \x01(\x08H\x00\x12\x17\n\rset_time_only\x18+ \x01(\x07H\x00\x12\x1d\n\x13\x62\x65gin_edit_settings\x18@ \x01(\x08H\x00\x12\x1e\n\x14\x63ommit_edit_settings\x18\x41 \x01(\x08H\x00\x12\x1e\n\x14\x66\x61\x63tory_reset_device\x18^ \x01(\x05H\x00\x12\x1c\n\x12reboot_ota_seconds\x18_ \x01(\x05H\x00\x12\x18\n\x0e\x65xit_simulator\x18` \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18\x61 \x01(\x05H\x00\x12\x1a\n\x10shutdown_seconds\x18\x62 \x01(\x05H\x00\x12\x1e\n\x14\x66\x61\x63tory_reset_config\x18\x63 \x01(\x05H\x00\x12\x16\n\x0cnodedb_reset\x18\x64 \x01(\x05H\x00\"\xc1\x01\n\nConfigType\x12\x11\n\rDEVICE_CONFIG\x10\x00\x12\x13\n\x0fPOSITION_CONFIG\x10\x01\x12\x10\n\x0cPOWER_CONFIG\x10\x02\x12\x12\n\x0eNETWORK_CONFIG\x10\x03\x12\x12\n\x0e\x44ISPLAY_CONFIG\x10\x04\x12\x0f\n\x0bLORA_CONFIG\x10\x05\x12\x14\n\x10\x42LUETOOTH_CONFIG\x10\x06\x12\x13\n\x0fSECURITY_CONFIG\x10\x07\x12\x15\n\x11SESSIONKEY_CONFIG\x10\x08\"\xbb\x02\n\x10ModuleConfigType\x12\x0f\n\x0bMQTT_CONFIG\x10\x00\x12\x11\n\rSERIAL_CONFIG\x10\x01\x12\x13\n\x0f\x45XTNOTIF_CONFIG\x10\x02\x12\x17\n\x13STOREFORWARD_CONFIG\x10\x03\x12\x14\n\x10RANGETEST_CONFIG\x10\x04\x12\x14\n\x10TELEMETRY_CONFIG\x10\x05\x12\x14\n\x10\x43\x41NNEDMSG_CONFIG\x10\x06\x12\x10\n\x0c\x41UDIO_CONFIG\x10\x07\x12\x19\n\x15REMOTEHARDWARE_CONFIG\x10\x08\x12\x17\n\x13NEIGHBORINFO_CONFIG\x10\t\x12\x1a\n\x16\x41MBIENTLIGHTING_CONFIG\x10\n\x12\x1a\n\x16\x44\x45TECTIONSENSOR_CONFIG\x10\x0b\x12\x15\n\x11PAXCOUNTER_CONFIG\x10\x0c\x42\x11\n\x0fpayload_variant\"[\n\rHamParameters\x12\x11\n\tcall_sign\x18\x01 \x01(\t\x12\x10\n\x08tx_power\x18\x02 \x01(\x05\x12\x11\n\tfrequency\x18\x03 \x01(\x02\x12\x12\n\nshort_name\x18\x04 \x01(\t\"o\n\x1eNodeRemoteHardwarePinsResponse\x12M\n\x19node_remote_hardware_pins\x18\x01 \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePinB`\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals() _globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -27,13 +27,13 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\013AdminProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_ADMINMESSAGE']._serialized_start=244 _globals['_ADMINMESSAGE']._serialized_start=244
_globals['_ADMINMESSAGE']._serialized_end=2654 _globals['_ADMINMESSAGE']._serialized_end=2787
_globals['_ADMINMESSAGE_CONFIGTYPE']._serialized_start=2168 _globals['_ADMINMESSAGE_CONFIGTYPE']._serialized_start=2257
_globals['_ADMINMESSAGE_CONFIGTYPE']._serialized_end=2317 _globals['_ADMINMESSAGE_CONFIGTYPE']._serialized_end=2450
_globals['_ADMINMESSAGE_MODULECONFIGTYPE']._serialized_start=2320 _globals['_ADMINMESSAGE_MODULECONFIGTYPE']._serialized_start=2453
_globals['_ADMINMESSAGE_MODULECONFIGTYPE']._serialized_end=2635 _globals['_ADMINMESSAGE_MODULECONFIGTYPE']._serialized_end=2768
_globals['_HAMPARAMETERS']._serialized_start=2656 _globals['_HAMPARAMETERS']._serialized_start=2789
_globals['_HAMPARAMETERS']._serialized_end=2747 _globals['_HAMPARAMETERS']._serialized_end=2880
_globals['_NODEREMOTEHARDWAREPINSRESPONSE']._serialized_start=2749 _globals['_NODEREMOTEHARDWAREPINSRESPONSE']._serialized_start=2882
_globals['_NODEREMOTEHARDWAREPINSRESPONSE']._serialized_end=2860 _globals['_NODEREMOTEHARDWAREPINSRESPONSE']._serialized_end=2993
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -68,6 +68,12 @@ class AdminMessage(google.protobuf.message.Message):
""" """
TODO: REPLACE TODO: REPLACE
""" """
SECURITY_CONFIG: AdminMessage._ConfigType.ValueType # 7
"""
TODO: REPLACE
"""
SESSIONKEY_CONFIG: AdminMessage._ConfigType.ValueType # 8
""""""
class ConfigType(_ConfigType, metaclass=_ConfigTypeEnumTypeWrapper): class ConfigType(_ConfigType, metaclass=_ConfigTypeEnumTypeWrapper):
""" """
@@ -102,6 +108,12 @@ class AdminMessage(google.protobuf.message.Message):
""" """
TODO: REPLACE TODO: REPLACE
""" """
SECURITY_CONFIG: AdminMessage.ConfigType.ValueType # 7
"""
TODO: REPLACE
"""
SESSIONKEY_CONFIG: AdminMessage.ConfigType.ValueType # 8
""""""
class _ModuleConfigType: class _ModuleConfigType:
ValueType = typing.NewType("ValueType", builtins.int) ValueType = typing.NewType("ValueType", builtins.int)
@@ -220,6 +232,7 @@ class AdminMessage(google.protobuf.message.Message):
TODO: REPLACE TODO: REPLACE
""" """
SESSION_PASSKEY_FIELD_NUMBER: builtins.int
GET_CHANNEL_REQUEST_FIELD_NUMBER: builtins.int GET_CHANNEL_REQUEST_FIELD_NUMBER: builtins.int
GET_CHANNEL_RESPONSE_FIELD_NUMBER: builtins.int GET_CHANNEL_RESPONSE_FIELD_NUMBER: builtins.int
GET_OWNER_REQUEST_FIELD_NUMBER: builtins.int GET_OWNER_REQUEST_FIELD_NUMBER: builtins.int
@@ -253,14 +266,22 @@ class AdminMessage(google.protobuf.message.Message):
REMOVE_FAVORITE_NODE_FIELD_NUMBER: builtins.int REMOVE_FAVORITE_NODE_FIELD_NUMBER: builtins.int
SET_FIXED_POSITION_FIELD_NUMBER: builtins.int SET_FIXED_POSITION_FIELD_NUMBER: builtins.int
REMOVE_FIXED_POSITION_FIELD_NUMBER: builtins.int REMOVE_FIXED_POSITION_FIELD_NUMBER: builtins.int
SET_TIME_ONLY_FIELD_NUMBER: builtins.int
BEGIN_EDIT_SETTINGS_FIELD_NUMBER: builtins.int BEGIN_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
COMMIT_EDIT_SETTINGS_FIELD_NUMBER: builtins.int COMMIT_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
FACTORY_RESET_DEVICE_FIELD_NUMBER: builtins.int
REBOOT_OTA_SECONDS_FIELD_NUMBER: builtins.int REBOOT_OTA_SECONDS_FIELD_NUMBER: builtins.int
EXIT_SIMULATOR_FIELD_NUMBER: builtins.int EXIT_SIMULATOR_FIELD_NUMBER: builtins.int
REBOOT_SECONDS_FIELD_NUMBER: builtins.int REBOOT_SECONDS_FIELD_NUMBER: builtins.int
SHUTDOWN_SECONDS_FIELD_NUMBER: builtins.int SHUTDOWN_SECONDS_FIELD_NUMBER: builtins.int
FACTORY_RESET_FIELD_NUMBER: builtins.int FACTORY_RESET_CONFIG_FIELD_NUMBER: builtins.int
NODEDB_RESET_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 get_channel_request: builtins.int
""" """
Send the specified channel in the response to this message Send the specified channel in the response to this message
@@ -343,6 +364,11 @@ class AdminMessage(google.protobuf.message.Message):
""" """
Clear fixed position coordinates and then set position.fixed_position = false 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
"""
begin_edit_settings: builtins.bool begin_edit_settings: builtins.bool
""" """
Begins an edit transaction for config, module config, owner, and channel settings changes Begins an edit transaction for config, module config, owner, and channel settings changes
@@ -352,6 +378,10 @@ class AdminMessage(google.protobuf.message.Message):
""" """
Commits an open transaction for any edits made to config, module config, owner, and channel settings Commits an open transaction for any edits made to config, module config, owner, and channel settings
""" """
factory_reset_device: builtins.int
"""
Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared.
"""
reboot_ota_seconds: builtins.int reboot_ota_seconds: builtins.int
""" """
Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
@@ -370,9 +400,9 @@ class AdminMessage(google.protobuf.message.Message):
""" """
Tell the node to shutdown in this many seconds (or <0 to cancel shutdown) Tell the node to shutdown in this many seconds (or <0 to cancel shutdown)
""" """
factory_reset: builtins.int factory_reset_config: builtins.int
""" """
Tell the node to factory reset, all device settings will be returned to factory defaults. Tell the node to factory reset config; all device state and configuration will be returned to factory defaults; BLE bonds will be preserved.
""" """
nodedb_reset: builtins.int nodedb_reset: builtins.int
""" """
@@ -463,6 +493,7 @@ class AdminMessage(google.protobuf.message.Message):
def __init__( def __init__(
self, self,
*, *,
session_passkey: builtins.bytes = ...,
get_channel_request: builtins.int = ..., get_channel_request: builtins.int = ...,
get_channel_response: meshtastic.protobuf.channel_pb2.Channel | None = ..., get_channel_response: meshtastic.protobuf.channel_pb2.Channel | None = ...,
get_owner_request: builtins.bool = ..., get_owner_request: builtins.bool = ...,
@@ -496,18 +527,20 @@ class AdminMessage(google.protobuf.message.Message):
remove_favorite_node: builtins.int = ..., remove_favorite_node: builtins.int = ...,
set_fixed_position: meshtastic.protobuf.mesh_pb2.Position | None = ..., set_fixed_position: meshtastic.protobuf.mesh_pb2.Position | None = ...,
remove_fixed_position: builtins.bool = ..., remove_fixed_position: builtins.bool = ...,
set_time_only: builtins.int = ...,
begin_edit_settings: builtins.bool = ..., begin_edit_settings: builtins.bool = ...,
commit_edit_settings: builtins.bool = ..., commit_edit_settings: builtins.bool = ...,
factory_reset_device: builtins.int = ...,
reboot_ota_seconds: builtins.int = ..., reboot_ota_seconds: builtins.int = ...,
exit_simulator: builtins.bool = ..., exit_simulator: builtins.bool = ...,
reboot_seconds: builtins.int = ..., reboot_seconds: builtins.int = ...,
shutdown_seconds: builtins.int = ..., shutdown_seconds: builtins.int = ...,
factory_reset: builtins.int = ..., factory_reset_config: builtins.int = ...,
nodedb_reset: builtins.int = ..., nodedb_reset: builtins.int = ...,
) -> None: ... ) -> 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", b"factory_reset", "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 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", "set_time_only", b"set_time_only", "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", b"factory_reset", "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 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", "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_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"]) -> 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", "reboot_ota_seconds", "exit_simulator", "reboot_seconds", "shutdown_seconds", "factory_reset", "nodedb_reset"] | 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", "set_time_only", "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 global___AdminMessage = AdminMessage

View File

@@ -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() _globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,20 +21,20 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.atak_pb
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\nATAKProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' 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_start=721
_globals['_TEAM']._serialized_end=895 _globals['_TEAM']._serialized_end=913
_globals['_MEMBERROLE']._serialized_start=897 _globals['_MEMBERROLE']._serialized_start=915
_globals['_MEMBERROLE']._serialized_end=1024 _globals['_MEMBERROLE']._serialized_end=1042
_globals['_TAKPACKET']._serialized_start=56 _globals['_TAKPACKET']._serialized_start=56
_globals['_TAKPACKET']._serialized_end=331 _globals['_TAKPACKET']._serialized_end=349
_globals['_GEOCHAT']._serialized_start=333 _globals['_GEOCHAT']._serialized_start=351
_globals['_GEOCHAT']._serialized_end=425 _globals['_GEOCHAT']._serialized_end=443
_globals['_GROUP']._serialized_start=427 _globals['_GROUP']._serialized_start=445
_globals['_GROUP']._serialized_end=522 _globals['_GROUP']._serialized_end=540
_globals['_STATUS']._serialized_start=524 _globals['_STATUS']._serialized_start=542
_globals['_STATUS']._serialized_end=549 _globals['_STATUS']._serialized_end=567
_globals['_CONTACT']._serialized_start=551 _globals['_CONTACT']._serialized_start=569
_globals['_CONTACT']._serialized_end=603 _globals['_CONTACT']._serialized_end=621
_globals['_PLI']._serialized_start=605 _globals['_PLI']._serialized_start=623
_globals['_PLI']._serialized_end=700 _globals['_PLI']._serialized_end=718
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -248,10 +248,16 @@ class TAKPacket(google.protobuf.message.Message):
STATUS_FIELD_NUMBER: builtins.int STATUS_FIELD_NUMBER: builtins.int
PLI_FIELD_NUMBER: builtins.int PLI_FIELD_NUMBER: builtins.int
CHAT_FIELD_NUMBER: builtins.int CHAT_FIELD_NUMBER: builtins.int
DETAIL_FIELD_NUMBER: builtins.int
is_compressed: builtins.bool is_compressed: builtins.bool
""" """
Are the payloads strings compressed for LoRA transport? Are the payloads strings compressed for LoRA transport?
""" """
detail: builtins.bytes
"""
Generic CoT detail XML
May be compressed / truncated by the sender
"""
@property @property
def contact(self) -> global___Contact: def contact(self) -> global___Contact:
""" """
@@ -291,10 +297,11 @@ class TAKPacket(google.protobuf.message.Message):
status: global___Status | None = ..., status: global___Status | None = ...,
pli: global___PLI | None = ..., pli: global___PLI | None = ...,
chat: global___GeoChat | None = ..., chat: global___GeoChat | None = ...,
detail: builtins.bytes = ...,
) -> None: ... ) -> 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 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", "group", b"group", "is_compressed", b"is_compressed", "payload_variant", b"payload_variant", "pli", b"pli", "status", b"status"]) -> None: ... 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"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["pli", "chat", "detail"] | None: ...
global___TAKPacket = TAKPacket global___TAKPacket = TAKPacket

View File

@@ -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 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() _globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -22,6 +23,6 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.cliento
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\020ClientOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' 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_start=131
_globals['_DEVICEPROFILE']._serialized_end=386 _globals['_DEVICEPROFILE']._serialized_end=583
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -7,6 +7,7 @@ import builtins
import google.protobuf.descriptor import google.protobuf.descriptor
import google.protobuf.message import google.protobuf.message
import meshtastic.protobuf.localonly_pb2 import meshtastic.protobuf.localonly_pb2
import meshtastic.protobuf.mesh_pb2
import typing import typing
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
@@ -25,6 +26,9 @@ class DeviceProfile(google.protobuf.message.Message):
CHANNEL_URL_FIELD_NUMBER: builtins.int CHANNEL_URL_FIELD_NUMBER: builtins.int
CONFIG_FIELD_NUMBER: builtins.int CONFIG_FIELD_NUMBER: builtins.int
MODULE_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: builtins.str
""" """
Long name for the node Long name for the node
@@ -37,6 +41,14 @@ class DeviceProfile(google.protobuf.message.Message):
""" """
The url of the channels from our node The url of the channels from our node
""" """
ringtone: builtins.str
"""
Ringtone for ExternalNotification
"""
canned_messages: builtins.str
"""
Predefined messages for CannedMessage
"""
@property @property
def config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig: def config(self) -> meshtastic.protobuf.localonly_pb2.LocalConfig:
""" """
@@ -49,6 +61,12 @@ class DeviceProfile(google.protobuf.message.Message):
The ModuleConfig of the node The ModuleConfig of the node
""" """
@property
def fixed_position(self) -> meshtastic.protobuf.mesh_pb2.Position:
"""
Fixed position data
"""
def __init__( def __init__(
self, self,
*, *,
@@ -57,18 +75,27 @@ class DeviceProfile(google.protobuf.message.Message):
channel_url: builtins.str | None = ..., channel_url: builtins.str | None = ...,
config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ..., config: meshtastic.protobuf.localonly_pb2.LocalConfig | None = ...,
module_config: meshtastic.protobuf.localonly_pb2.LocalModuleConfig | 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: ... ) -> 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 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["_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 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 @typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_channel_url", b"_channel_url"]) -> typing.Literal["channel_url"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["_channel_url", b"_channel_url"]) -> typing.Literal["channel_url"] | None: ...
@typing.overload @typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_config", b"_config"]) -> typing.Literal["config"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["_config", b"_config"]) -> typing.Literal["config"] | None: ...
@typing.overload @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: ... def WhichOneof(self, oneof_group: typing.Literal["_long_name", b"_long_name"]) -> typing.Literal["long_name"] | None: ...
@typing.overload @typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_module_config", b"_module_config"]) -> typing.Literal["module_config"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["_module_config", b"_module_config"]) -> typing.Literal["module_config"] | None: ...
@typing.overload @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: ... def WhichOneof(self, oneof_group: typing.Literal["_short_name", b"_short_name"]) -> typing.Literal["short_name"] | None: ...
global___DeviceProfile = DeviceProfile global___DeviceProfile = DeviceProfile

View File

File diff suppressed because one or more lines are too long

View File

@@ -239,7 +239,6 @@ class Config(google.protobuf.message.Message):
ROLE_FIELD_NUMBER: builtins.int ROLE_FIELD_NUMBER: builtins.int
SERIAL_ENABLED_FIELD_NUMBER: builtins.int SERIAL_ENABLED_FIELD_NUMBER: builtins.int
DEBUG_LOG_ENABLED_FIELD_NUMBER: builtins.int
BUTTON_GPIO_FIELD_NUMBER: builtins.int BUTTON_GPIO_FIELD_NUMBER: builtins.int
BUZZER_GPIO_FIELD_NUMBER: builtins.int BUZZER_GPIO_FIELD_NUMBER: builtins.int
REBROADCAST_MODE_FIELD_NUMBER: builtins.int REBROADCAST_MODE_FIELD_NUMBER: builtins.int
@@ -256,11 +255,7 @@ class Config(google.protobuf.message.Message):
serial_enabled: builtins.bool serial_enabled: builtins.bool
""" """
Disabling this will disable the SerialConsole by not initilizing the StreamAPI Disabling this will disable the SerialConsole by not initilizing the StreamAPI
""" Moved to SecurityConfig
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.
""" """
button_gpio: builtins.int button_gpio: builtins.int
""" """
@@ -289,6 +284,7 @@ class Config(google.protobuf.message.Message):
""" """
If true, device is considered to be "managed" by a mesh administrator 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 Clients should then limit available configuration and administrative options inside the user interface
Moved to SecurityConfig
""" """
disable_triple_click: builtins.bool disable_triple_click: builtins.bool
""" """
@@ -307,7 +303,6 @@ class Config(google.protobuf.message.Message):
*, *,
role: global___Config.DeviceConfig.Role.ValueType = ..., role: global___Config.DeviceConfig.Role.ValueType = ...,
serial_enabled: builtins.bool = ..., serial_enabled: builtins.bool = ...,
debug_log_enabled: builtins.bool = ...,
button_gpio: builtins.int = ..., button_gpio: builtins.int = ...,
buzzer_gpio: builtins.int = ..., buzzer_gpio: builtins.int = ...,
rebroadcast_mode: global___Config.DeviceConfig.RebroadcastMode.ValueType = ..., rebroadcast_mode: global___Config.DeviceConfig.RebroadcastMode.ValueType = ...,
@@ -318,7 +313,7 @@ class Config(google.protobuf.message.Message):
tzdef: builtins.str = ..., tzdef: builtins.str = ...,
led_heartbeat_disabled: builtins.bool = ..., led_heartbeat_disabled: builtins.bool = ...,
) -> None: ... ) -> 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 @typing.final
class PositionConfig(google.protobuf.message.Message): class PositionConfig(google.protobuf.message.Message):
@@ -1303,6 +1298,7 @@ class Config(google.protobuf.message.Message):
VERY_LONG_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 2 VERY_LONG_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 2
""" """
Very Long Range - Slow Very Long Range - Slow
Deprecated in 2.5: Works only with txco and is unusably slow
""" """
MEDIUM_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 3 MEDIUM_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 3
""" """
@@ -1324,6 +1320,12 @@ class Config(google.protobuf.message.Message):
""" """
Long Range - Moderately Fast 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): class ModemPreset(_ModemPreset, metaclass=_ModemPresetEnumTypeWrapper):
""" """
@@ -1342,6 +1344,7 @@ class Config(google.protobuf.message.Message):
VERY_LONG_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 2 VERY_LONG_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 2
""" """
Very Long Range - Slow Very Long Range - Slow
Deprecated in 2.5: Works only with txco and is unusably slow
""" """
MEDIUM_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 3 MEDIUM_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 3
""" """
@@ -1363,6 +1366,12 @@ class Config(google.protobuf.message.Message):
""" """
Long Range - Moderately Fast 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 USE_PRESET_FIELD_NUMBER: builtins.int
MODEM_PRESET_FIELD_NUMBER: builtins.int MODEM_PRESET_FIELD_NUMBER: builtins.int
@@ -1381,6 +1390,7 @@ class Config(google.protobuf.message.Message):
PA_FAN_DISABLED_FIELD_NUMBER: builtins.int PA_FAN_DISABLED_FIELD_NUMBER: builtins.int
IGNORE_INCOMING_FIELD_NUMBER: builtins.int IGNORE_INCOMING_FIELD_NUMBER: builtins.int
IGNORE_MQTT_FIELD_NUMBER: builtins.int IGNORE_MQTT_FIELD_NUMBER: builtins.int
CONFIG_OK_TO_MQTT_FIELD_NUMBER: builtins.int
use_preset: builtins.bool use_preset: builtins.bool
""" """
When enabled, the `modem_preset` fields will be adhered to, else the `bandwidth`/`spread_factor`/`coding_rate` When enabled, the `modem_preset` fields will be adhered to, else the `bandwidth`/`spread_factor`/`coding_rate`
@@ -1474,6 +1484,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. 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 @property
def ignore_incoming(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: def ignore_incoming(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]:
""" """
@@ -1502,8 +1516,9 @@ class Config(google.protobuf.message.Message):
pa_fan_disabled: builtins.bool = ..., pa_fan_disabled: builtins.bool = ...,
ignore_incoming: collections.abc.Iterable[builtins.int] | None = ..., ignore_incoming: collections.abc.Iterable[builtins.int] | None = ...,
ignore_mqtt: builtins.bool = ..., ignore_mqtt: builtins.bool = ...,
config_ok_to_mqtt: builtins.bool = ...,
) -> None: ... ) -> 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 @typing.final
class BluetoothConfig(google.protobuf.message.Message): class BluetoothConfig(google.protobuf.message.Message):
@@ -1545,7 +1560,6 @@ class Config(google.protobuf.message.Message):
ENABLED_FIELD_NUMBER: builtins.int ENABLED_FIELD_NUMBER: builtins.int
MODE_FIELD_NUMBER: builtins.int MODE_FIELD_NUMBER: builtins.int
FIXED_PIN_FIELD_NUMBER: builtins.int FIXED_PIN_FIELD_NUMBER: builtins.int
DEVICE_LOGGING_ENABLED_FIELD_NUMBER: builtins.int
enabled: builtins.bool enabled: builtins.bool
""" """
Enable Bluetooth on the device Enable Bluetooth on the device
@@ -1558,19 +1572,84 @@ class Config(google.protobuf.message.Message):
""" """
Specified PIN for PairingMode.FixedPin Specified PIN for PairingMode.FixedPin
""" """
device_logging_enabled: builtins.bool
"""
Enables device (serial style logs) over Bluetooth
"""
def __init__( def __init__(
self, self,
*, *,
enabled: builtins.bool = ..., enabled: builtins.bool = ...,
mode: global___Config.BluetoothConfig.PairingMode.ValueType = ..., mode: global___Config.BluetoothConfig.PairingMode.ValueType = ...,
fixed_pin: builtins.int = ..., fixed_pin: builtins.int = ...,
device_logging_enabled: builtins.bool = ...,
) -> None: ... ) -> 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 DEVICE_FIELD_NUMBER: builtins.int
POSITION_FIELD_NUMBER: builtins.int POSITION_FIELD_NUMBER: builtins.int
@@ -1579,6 +1658,8 @@ class Config(google.protobuf.message.Message):
DISPLAY_FIELD_NUMBER: builtins.int DISPLAY_FIELD_NUMBER: builtins.int
LORA_FIELD_NUMBER: builtins.int LORA_FIELD_NUMBER: builtins.int
BLUETOOTH_FIELD_NUMBER: builtins.int BLUETOOTH_FIELD_NUMBER: builtins.int
SECURITY_FIELD_NUMBER: builtins.int
SESSIONKEY_FIELD_NUMBER: builtins.int
@property @property
def device(self) -> global___Config.DeviceConfig: ... def device(self) -> global___Config.DeviceConfig: ...
@property @property
@@ -1593,6 +1674,10 @@ class Config(google.protobuf.message.Message):
def lora(self) -> global___Config.LoRaConfig: ... def lora(self) -> global___Config.LoRaConfig: ...
@property @property
def bluetooth(self) -> global___Config.BluetoothConfig: ... def bluetooth(self) -> global___Config.BluetoothConfig: ...
@property
def security(self) -> global___Config.SecurityConfig: ...
@property
def sessionkey(self) -> global___Config.SessionkeyConfig: ...
def __init__( def __init__(
self, self,
*, *,
@@ -1603,9 +1688,11 @@ class Config(google.protobuf.message.Message):
display: global___Config.DisplayConfig | None = ..., display: global___Config.DisplayConfig | None = ...,
lora: global___Config.LoRaConfig | None = ..., lora: global___Config.LoRaConfig | None = ...,
bluetooth: global___Config.BluetoothConfig | None = ..., bluetooth: global___Config.BluetoothConfig | None = ...,
security: global___Config.SecurityConfig | None = ...,
sessionkey: global___Config.SessionkeyConfig | None = ...,
) -> 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 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", "security", b"security", "sessionkey", b"sessionkey"]) -> 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 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", "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"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["device", "position", "power", "network", "display", "lora", "bluetooth", "security", "sessionkey"] | None: ...
global___Config = Config global___Config = Config

View File

@@ -15,10 +15,11 @@ from meshtastic.protobuf import channel_pb2 as meshtastic_dot_protobuf_dot_chann
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__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 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 telemetry_pb2 as meshtastic_dot_protobuf_dot_telemetry__pb2
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
import nanopb_pb2 as nanopb__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#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/config.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\"\xb8\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\x42\x0c\n\n_hops_away\"\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')
_globals = globals() _globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -26,20 +27,24 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.deviceo
if _descriptor._USE_C_DESCRIPTORS == False: if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None 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>' 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']._options = None
_DEVICESTATE.fields_by_name['no_save']._serialized_options = b'\030\001' _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']._options = None
_DEVICESTATE.fields_by_name['node_db_lite']._serialized_options = b'\222?\'\222\001$std::vector<meshtastic_NodeInfoLite>' _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_start=1856
_globals['_SCREENFONTS']._serialized_end=1632 _globals['_SCREENFONTS']._serialized_end=1918
_globals['_POSITIONLITE']._serialized_start=217 _globals['_POSITIONLITE']._serialized_start=251
_globals['_POSITIONLITE']._serialized_end=370 _globals['_POSITIONLITE']._serialized_end=404
_globals['_NODEINFOLITE']._serialized_start=373 _globals['_USERLITE']._serialized_start=407
_globals['_NODEINFOLITE']._serialized_end=662 _globals['_USERLITE']._serialized_end=633
_globals['_DEVICESTATE']._serialized_start=665 _globals['_NODEINFOLITE']._serialized_start=636
_globals['_DEVICESTATE']._serialized_end=1179 _globals['_NODEINFOLITE']._serialized_end=948
_globals['_CHANNELFILE']._serialized_start=1181 _globals['_DEVICESTATE']._serialized_start=951
_globals['_CHANNELFILE']._serialized_end=1259 _globals['_DEVICESTATE']._serialized_end=1465
_globals['_OEMSTORE']._serialized_start=1262 _globals['_CHANNELFILE']._serialized_start=1467
_globals['_OEMSTORE']._serialized_end=1568 _globals['_CHANNELFILE']._serialized_end=1545
_globals['_OEMSTORE']._serialized_start=1548
_globals['_OEMSTORE']._serialized_end=1854
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -10,6 +10,7 @@ import google.protobuf.internal.containers
import google.protobuf.internal.enum_type_wrapper import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message import google.protobuf.message
import meshtastic.protobuf.channel_pb2 import meshtastic.protobuf.channel_pb2
import meshtastic.protobuf.config_pb2
import meshtastic.protobuf.localonly_pb2 import meshtastic.protobuf.localonly_pb2
import meshtastic.protobuf.mesh_pb2 import meshtastic.protobuf.mesh_pb2
import meshtastic.protobuf.telemetry_pb2 import meshtastic.protobuf.telemetry_pb2
@@ -112,6 +113,67 @@ class PositionLite(google.protobuf.message.Message):
global___PositionLite = PositionLite 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 @typing.final
class NodeInfoLite(google.protobuf.message.Message): class NodeInfoLite(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor DESCRIPTOR: google.protobuf.descriptor.Descriptor
@@ -157,7 +219,7 @@ class NodeInfoLite(google.protobuf.message.Message):
Persists between NodeDB internal clean ups Persists between NodeDB internal clean ups
""" """
@property @property
def user(self) -> meshtastic.protobuf.mesh_pb2.User: def user(self) -> global___UserLite:
""" """
The user info for this node The user info for this node
""" """
@@ -179,18 +241,19 @@ class NodeInfoLite(google.protobuf.message.Message):
self, self,
*, *,
num: builtins.int = ..., num: builtins.int = ...,
user: meshtastic.protobuf.mesh_pb2.User | None = ..., user: global___UserLite | None = ...,
position: global___PositionLite | None = ..., position: global___PositionLite | None = ...,
snr: builtins.float = ..., snr: builtins.float = ...,
last_heard: builtins.int = ..., last_heard: builtins.int = ...,
device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ..., device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ...,
channel: builtins.int = ..., channel: builtins.int = ...,
via_mqtt: builtins.bool = ..., via_mqtt: builtins.bool = ...,
hops_away: builtins.int = ..., hops_away: builtins.int | None = ...,
is_favorite: builtins.bool = ..., is_favorite: builtins.bool = ...,
) -> None: ... ) -> None: ...
def HasField(self, field_name: typing.Literal["device_metrics", b"device_metrics", "position", b"position", "user", b"user"]) -> builtins.bool: ... 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["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 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", "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___NodeInfoLite = NodeInfoLite global___NodeInfoLite = NodeInfoLite

View File

@@ -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 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() _globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -24,7 +24,7 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\017LocalOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' 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_start=136
_globals['_LOCALCONFIG']._serialized_end=580 _globals['_LOCALCONFIG']._serialized_end=642
_globals['_LOCALMODULECONFIG']._serialized_start=583 _globals['_LOCALMODULECONFIG']._serialized_start=645
_globals['_LOCALMODULECONFIG']._serialized_end=1591 _globals['_LOCALMODULECONFIG']._serialized_end=1653
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -29,6 +29,7 @@ class LocalConfig(google.protobuf.message.Message):
LORA_FIELD_NUMBER: builtins.int LORA_FIELD_NUMBER: builtins.int
BLUETOOTH_FIELD_NUMBER: builtins.int BLUETOOTH_FIELD_NUMBER: builtins.int
VERSION_FIELD_NUMBER: builtins.int VERSION_FIELD_NUMBER: builtins.int
SECURITY_FIELD_NUMBER: builtins.int
version: builtins.int version: builtins.int
""" """
A version integer used to invalidate old save files when we make 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 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__( def __init__(
self, self,
*, *,
@@ -88,9 +95,10 @@ class LocalConfig(google.protobuf.message.Message):
lora: meshtastic.protobuf.config_pb2.Config.LoRaConfig | None = ..., lora: meshtastic.protobuf.config_pb2.Config.LoRaConfig | None = ...,
bluetooth: meshtastic.protobuf.config_pb2.Config.BluetoothConfig | None = ..., bluetooth: meshtastic.protobuf.config_pb2.Config.BluetoothConfig | None = ...,
version: builtins.int = ..., version: builtins.int = ...,
security: meshtastic.protobuf.config_pb2.Config.SecurityConfig | None = ...,
) -> 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 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", "version", b"version"]) -> None: ... 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 global___LocalConfig = LocalConfig

View File

File diff suppressed because one or more lines are too long

View File

@@ -129,6 +129,10 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
""" """
Heltec HRU-3601: https://heltec.org/project/hru-3601/ Heltec HRU-3601: https://heltec.org/project/hru-3601/
""" """
HELTEC_WIRELESS_BRIDGE: _HardwareModel.ValueType # 24
"""
Heltec Wireless Bridge
"""
STATION_G1: _HardwareModel.ValueType # 25 STATION_G1: _HardwareModel.ValueType # 25
""" """
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
@@ -201,7 +205,7 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
""" """
M5STACK: _HardwareModel.ValueType # 42 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 HELTEC_V3: _HardwareModel.ValueType # 43
""" """
@@ -332,6 +336,49 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
""" """
Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors. Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors.
""" """
RAK3172: _HardwareModel.ValueType # 72
"""
RAK3172 STM32WLE5 Module (https://store.rakwireless.com/products/wisduo-lpwan-module-rak3172)
"""
WIO_E5: _HardwareModel.ValueType # 73
"""
Seeed Studio Wio-E5 (either mini or Dev kit) using STM32WL chip.
"""
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
"""
PRIVATE_HW: _HardwareModel.ValueType # 255 PRIVATE_HW: _HardwareModel.ValueType # 255
""" """
------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------
@@ -445,6 +492,10 @@ HELTEC_HRU_3601: HardwareModel.ValueType # 23
""" """
Heltec HRU-3601: https://heltec.org/project/hru-3601/ Heltec HRU-3601: https://heltec.org/project/hru-3601/
""" """
HELTEC_WIRELESS_BRIDGE: HardwareModel.ValueType # 24
"""
Heltec Wireless Bridge
"""
STATION_G1: HardwareModel.ValueType # 25 STATION_G1: HardwareModel.ValueType # 25
""" """
B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
@@ -517,7 +568,7 @@ Custom Disaster Radio esp32 v3 device https://github.com/sudomesh/disaster-radio
""" """
M5STACK: HardwareModel.ValueType # 42 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 HELTEC_V3: HardwareModel.ValueType # 43
""" """
@@ -648,6 +699,49 @@ TRACKER_T1000_E: HardwareModel.ValueType # 71
""" """
Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors. Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors.
""" """
RAK3172: HardwareModel.ValueType # 72
"""
RAK3172 STM32WLE5 Module (https://store.rakwireless.com/products/wisduo-lpwan-module-rak3172)
"""
WIO_E5: HardwareModel.ValueType # 73
"""
Seeed Studio Wio-E5 (either mini or Dev kit) using STM32WL chip.
"""
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
"""
PRIVATE_HW: HardwareModel.ValueType # 255 PRIVATE_HW: HardwareModel.ValueType # 255
""" """
------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------
@@ -1073,22 +1167,22 @@ class Position(google.protobuf.message.Message):
def __init__( def __init__(
self, self,
*, *,
latitude_i: builtins.int = ..., latitude_i: builtins.int | None = ...,
longitude_i: builtins.int = ..., longitude_i: builtins.int | None = ...,
altitude: builtins.int = ..., altitude: builtins.int | None = ...,
time: builtins.int = ..., time: builtins.int = ...,
location_source: global___Position.LocSource.ValueType = ..., location_source: global___Position.LocSource.ValueType = ...,
altitude_source: global___Position.AltSource.ValueType = ..., altitude_source: global___Position.AltSource.ValueType = ...,
timestamp: builtins.int = ..., timestamp: builtins.int = ...,
timestamp_millis_adjust: builtins.int = ..., timestamp_millis_adjust: builtins.int = ...,
altitude_hae: builtins.int = ..., altitude_hae: builtins.int | None = ...,
altitude_geoidal_separation: builtins.int = ..., altitude_geoidal_separation: builtins.int | None = ...,
PDOP: builtins.int = ..., PDOP: builtins.int = ...,
HDOP: builtins.int = ..., HDOP: builtins.int = ...,
VDOP: builtins.int = ..., VDOP: builtins.int = ...,
gps_accuracy: builtins.int = ..., gps_accuracy: builtins.int = ...,
ground_speed: builtins.int = ..., ground_speed: builtins.int | None = ...,
ground_track: builtins.int = ..., ground_track: builtins.int | None = ...,
fix_quality: builtins.int = ..., fix_quality: builtins.int = ...,
fix_type: builtins.int = ..., fix_type: builtins.int = ...,
sats_in_view: builtins.int = ..., sats_in_view: builtins.int = ...,
@@ -1097,7 +1191,22 @@ class Position(google.protobuf.message.Message):
seq_number: builtins.int = ..., seq_number: builtins.int = ...,
precision_bits: builtins.int = ..., precision_bits: builtins.int = ...,
) -> None: ... ) -> 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 global___Position = Position
@@ -1135,6 +1244,7 @@ class User(google.protobuf.message.Message):
HW_MODEL_FIELD_NUMBER: builtins.int HW_MODEL_FIELD_NUMBER: builtins.int
IS_LICENSED_FIELD_NUMBER: builtins.int IS_LICENSED_FIELD_NUMBER: builtins.int
ROLE_FIELD_NUMBER: builtins.int ROLE_FIELD_NUMBER: builtins.int
PUBLIC_KEY_FIELD_NUMBER: builtins.int
id: builtins.str id: builtins.str
""" """
A globally unique ID string for this user. A globally unique ID string for this user.
@@ -1174,6 +1284,11 @@ class User(google.protobuf.message.Message):
""" """
Indicates that the user's role in the mesh 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__( def __init__(
self, self,
*, *,
@@ -1184,32 +1299,57 @@ class User(google.protobuf.message.Message):
hw_model: global___HardwareModel.ValueType = ..., hw_model: global___HardwareModel.ValueType = ...,
is_licensed: builtins.bool = ..., is_licensed: builtins.bool = ...,
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ..., role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
public_key: builtins.bytes = ...,
) -> None: ... ) -> 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 global___User = User
@typing.final @typing.final
class RouteDiscovery(google.protobuf.message.Message): 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 DESCRIPTOR: google.protobuf.descriptor.Descriptor
ROUTE_FIELD_NUMBER: builtins.int ROUTE_FIELD_NUMBER: builtins.int
SNR_TOWARDS_FIELD_NUMBER: builtins.int
ROUTE_BACK_FIELD_NUMBER: builtins.int
SNR_BACK_FIELD_NUMBER: builtins.int
@property @property
def route(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: 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__( def __init__(
self, self,
*, *,
route: collections.abc.Iterable[builtins.int] | None = ..., 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: ... ) -> 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 global___RouteDiscovery = RouteDiscovery
@@ -1277,6 +1417,22 @@ class Routing(google.protobuf.message.Message):
The application layer service on the remote node received your request, but considered your request not authorized 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) (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): class Error(_Error, metaclass=_ErrorEnumTypeWrapper):
""" """
@@ -1334,6 +1490,22 @@ class Routing(google.protobuf.message.Message):
The application layer service on the remote node received your request, but considered your request not authorized 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) (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_REQUEST_FIELD_NUMBER: builtins.int
ROUTE_REPLY_FIELD_NUMBER: builtins.int ROUTE_REPLY_FIELD_NUMBER: builtins.int
@@ -1386,6 +1558,7 @@ class Data(google.protobuf.message.Message):
REQUEST_ID_FIELD_NUMBER: builtins.int REQUEST_ID_FIELD_NUMBER: builtins.int
REPLY_ID_FIELD_NUMBER: builtins.int REPLY_ID_FIELD_NUMBER: builtins.int
EMOJI_FIELD_NUMBER: builtins.int EMOJI_FIELD_NUMBER: builtins.int
BITFIELD_FIELD_NUMBER: builtins.int
portnum: meshtastic.protobuf.portnums_pb2.PortNum.ValueType portnum: meshtastic.protobuf.portnums_pb2.PortNum.ValueType
""" """
Formerly named typ and of type Type Formerly named typ and of type Type
@@ -1428,6 +1601,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 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. 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__( def __init__(
self, self,
*, *,
@@ -1439,8 +1616,11 @@ class Data(google.protobuf.message.Message):
request_id: builtins.int = ..., request_id: builtins.int = ...,
reply_id: builtins.int = ..., reply_id: builtins.int = ...,
emoji: builtins.int = ..., emoji: builtins.int = ...,
bitfield: builtins.int | None = ...,
) -> 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 global___Data = Data
@@ -1497,15 +1677,20 @@ class Waypoint(google.protobuf.message.Message):
self, self,
*, *,
id: builtins.int = ..., id: builtins.int = ...,
latitude_i: builtins.int = ..., latitude_i: builtins.int | None = ...,
longitude_i: builtins.int = ..., longitude_i: builtins.int | None = ...,
expire: builtins.int = ..., expire: builtins.int = ...,
locked_to: builtins.int = ..., locked_to: builtins.int = ...,
name: builtins.str = ..., name: builtins.str = ...,
description: builtins.str = ..., description: builtins.str = ...,
icon: builtins.int = ..., icon: builtins.int = ...,
) -> None: ... ) -> 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 global___Waypoint = Waypoint
@@ -1589,6 +1774,15 @@ class MeshPacket(google.protobuf.message.Message):
If priority is unset but the message is marked as want_ack, If priority is unset but the message is marked as want_ack,
assume it is important and use a slightly higher priority 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.
"""
ACK: MeshPacket._Priority.ValueType # 120 ACK: MeshPacket._Priority.ValueType # 120
""" """
Ack/naks are sent with very high priority to ensure that retransmission Ack/naks are sent with very high priority to ensure that retransmission
@@ -1643,6 +1837,15 @@ class MeshPacket(google.protobuf.message.Message):
If priority is unset but the message is marked as want_ack, If priority is unset but the message is marked as want_ack,
assume it is important and use a slightly higher priority 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.
"""
ACK: MeshPacket.Priority.ValueType # 120 ACK: MeshPacket.Priority.ValueType # 120
""" """
Ack/naks are sent with very high priority to ensure that retransmission Ack/naks are sent with very high priority to ensure that retransmission
@@ -1705,6 +1908,8 @@ class MeshPacket(google.protobuf.message.Message):
DELAYED_FIELD_NUMBER: builtins.int DELAYED_FIELD_NUMBER: builtins.int
VIA_MQTT_FIELD_NUMBER: builtins.int VIA_MQTT_FIELD_NUMBER: builtins.int
HOP_START_FIELD_NUMBER: builtins.int HOP_START_FIELD_NUMBER: builtins.int
PUBLIC_KEY_FIELD_NUMBER: builtins.int
PKI_ENCRYPTED_FIELD_NUMBER: builtins.int
to: builtins.int to: builtins.int
""" """
The (immediate) destination for this packet The (immediate) destination for this packet
@@ -1788,6 +1993,14 @@ class MeshPacket(google.protobuf.message.Message):
Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header. 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. 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
"""
@property @property
def decoded(self) -> global___Data: def decoded(self) -> global___Data:
""" """
@@ -1811,9 +2024,11 @@ class MeshPacket(google.protobuf.message.Message):
delayed: global___MeshPacket.Delayed.ValueType = ..., delayed: global___MeshPacket.Delayed.ValueType = ...,
via_mqtt: builtins.bool = ..., via_mqtt: builtins.bool = ...,
hop_start: builtins.int = ..., hop_start: builtins.int = ...,
public_key: builtins.bytes = ...,
pki_encrypted: builtins.bool = ...,
) -> None: ... ) -> None: ...
def HasField(self, field_name: typing.Literal["decoded", b"decoded", "encrypted", b"encrypted", "payload_variant", b"payload_variant"]) -> builtins.bool: ... 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", "payload_variant", b"payload_variant", "pki_encrypted", b"pki_encrypted", "priority", b"priority", "public_key", b"public_key", "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 WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["decoded", "encrypted"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["decoded", "encrypted"] | None: ...
global___MeshPacket = MeshPacket global___MeshPacket = MeshPacket
@@ -1917,11 +2132,12 @@ class NodeInfo(google.protobuf.message.Message):
device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ..., device_metrics: meshtastic.protobuf.telemetry_pb2.DeviceMetrics | None = ...,
channel: builtins.int = ..., channel: builtins.int = ...,
via_mqtt: builtins.bool = ..., via_mqtt: builtins.bool = ...,
hops_away: builtins.int = ..., hops_away: builtins.int | None = ...,
is_favorite: builtins.bool = ..., is_favorite: builtins.bool = ...,
) -> None: ... ) -> None: ...
def HasField(self, field_name: typing.Literal["device_metrics", b"device_metrics", "position", b"position", "user", b"user"]) -> builtins.bool: ... 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["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 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", "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 global___NodeInfo = NodeInfo
@@ -2131,6 +2347,7 @@ class FromRadio(google.protobuf.message.Message):
METADATA_FIELD_NUMBER: builtins.int METADATA_FIELD_NUMBER: builtins.int
MQTTCLIENTPROXYMESSAGE_FIELD_NUMBER: builtins.int MQTTCLIENTPROXYMESSAGE_FIELD_NUMBER: builtins.int
FILEINFO_FIELD_NUMBER: builtins.int FILEINFO_FIELD_NUMBER: builtins.int
CLIENTNOTIFICATION_FIELD_NUMBER: builtins.int
id: builtins.int id: builtins.int
""" """
The packet id, used to allow the phone to request missing read packets from the FIFO, The packet id, used to allow the phone to request missing read packets from the FIFO,
@@ -2224,6 +2441,12 @@ class FromRadio(google.protobuf.message.Message):
File system manifest messages File system manifest messages
""" """
@property
def clientNotification(self) -> global___ClientNotification:
"""
Notification message to the client
"""
def __init__( def __init__(
self, self,
*, *,
@@ -2242,13 +2465,59 @@ class FromRadio(google.protobuf.message.Message):
metadata: global___DeviceMetadata | None = ..., metadata: global___DeviceMetadata | None = ...,
mqttClientProxyMessage: global___MqttClientProxyMessage | None = ..., mqttClientProxyMessage: global___MqttClientProxyMessage | None = ...,
fileInfo: global___FileInfo | None = ..., fileInfo: global___FileInfo | None = ...,
clientNotification: global___ClientNotification | None = ...,
) -> 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 HasField(self, field_name: typing.Literal["channel", b"channel", "clientNotification", b"clientNotification", "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 ClearField(self, field_name: typing.Literal["channel", b"channel", "clientNotification", b"clientNotification", "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 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"] | None: ...
global___FromRadio = FromRadio 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 @typing.final
class FileInfo(google.protobuf.message.Message): class FileInfo(google.protobuf.message.Message):
""" """
@@ -2479,6 +2748,7 @@ class DeviceMetadata(google.protobuf.message.Message):
POSITION_FLAGS_FIELD_NUMBER: builtins.int POSITION_FLAGS_FIELD_NUMBER: builtins.int
HW_MODEL_FIELD_NUMBER: builtins.int HW_MODEL_FIELD_NUMBER: builtins.int
HASREMOTEHARDWARE_FIELD_NUMBER: builtins.int HASREMOTEHARDWARE_FIELD_NUMBER: builtins.int
HASPKC_FIELD_NUMBER: builtins.int
firmware_version: builtins.str firmware_version: builtins.str
""" """
Device firmware version string Device firmware version string
@@ -2519,6 +2789,10 @@ class DeviceMetadata(google.protobuf.message.Message):
""" """
Has Remote Hardware enabled Has Remote Hardware enabled
""" """
hasPKC: builtins.bool
"""
Has PKC capabilities
"""
def __init__( def __init__(
self, self,
*, *,
@@ -2532,8 +2806,9 @@ class DeviceMetadata(google.protobuf.message.Message):
position_flags: builtins.int = ..., position_flags: builtins.int = ...,
hw_model: global___HardwareModel.ValueType = ..., hw_model: global___HardwareModel.ValueType = ...,
hasRemoteHardware: builtins.bool = ..., hasRemoteHardware: builtins.bool = ...,
hasPKC: builtins.bool = ...,
) -> None: ... ) -> 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", "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 global___DeviceMetadata = DeviceMetadata

View File

File diff suppressed because one or more lines are too long

View File

@@ -250,13 +250,54 @@ class ModuleConfig(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor 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 ENABLED_FIELD_NUMBER: builtins.int
MINIMUM_BROADCAST_SECS_FIELD_NUMBER: builtins.int MINIMUM_BROADCAST_SECS_FIELD_NUMBER: builtins.int
STATE_BROADCAST_SECS_FIELD_NUMBER: builtins.int STATE_BROADCAST_SECS_FIELD_NUMBER: builtins.int
SEND_BELL_FIELD_NUMBER: builtins.int SEND_BELL_FIELD_NUMBER: builtins.int
NAME_FIELD_NUMBER: builtins.int NAME_FIELD_NUMBER: builtins.int
MONITOR_PIN_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 USE_PULLUP_FIELD_NUMBER: builtins.int
enabled: builtins.bool enabled: builtins.bool
""" """
@@ -264,13 +305,15 @@ class ModuleConfig(google.protobuf.message.Message):
""" """
minimum_broadcast_secs: builtins.int 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 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 Interval in seconds of how often we should send a message to the mesh
When set to 0, only state changes will be broadcasted with the current state regardless of trigger events When set to 0, only
Works as a sort of status heartbeat for peace of mind trigger events will be broadcasted Works as a sort of status heartbeat
for peace of mind
""" """
send_bell: builtins.bool send_bell: builtins.bool
""" """
@@ -287,10 +330,9 @@ class ModuleConfig(google.protobuf.message.Message):
""" """
GPIO pin to monitor for state changes 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) The type of trigger event to be used
Otherwise LOW (0)
""" """
use_pullup: builtins.bool use_pullup: builtins.bool
""" """
@@ -306,10 +348,10 @@ class ModuleConfig(google.protobuf.message.Message):
send_bell: builtins.bool = ..., send_bell: builtins.bool = ...,
name: builtins.str = ..., name: builtins.str = ...,
monitor_pin: builtins.int = ..., monitor_pin: builtins.int = ...,
detection_triggered_high: builtins.bool = ..., detection_trigger_type: global___ModuleConfig.DetectionSensorConfig.TriggerType.ValueType = ...,
use_pullup: builtins.bool = ..., use_pullup: builtins.bool = ...,
) -> None: ... ) -> 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 @typing.final
class AudioConfig(google.protobuf.message.Message): class AudioConfig(google.protobuf.message.Message):
@@ -992,7 +1034,7 @@ class ModuleConfig(google.protobuf.message.Message):
allow_input_source: builtins.str allow_input_source: builtins.str
""" """
Input event origin accepted by the canned message module. 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 send_bell: builtins.bool
""" """

View File

@@ -154,7 +154,7 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy
TRACEROUTE_APP: _PortNum.ValueType # 70 TRACEROUTE_APP: _PortNum.ValueType # 70
""" """
Provides a traceroute functionality to show the route a packet towards 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 ENCODING: Protobuf
""" """
NEIGHBORINFO_APP: _PortNum.ValueType # 71 NEIGHBORINFO_APP: _PortNum.ValueType # 71
@@ -339,7 +339,7 @@ ENCODING: Protobuf (?)
TRACEROUTE_APP: PortNum.ValueType # 70 TRACEROUTE_APP: PortNum.ValueType # 70
""" """
Provides a traceroute functionality to show the route a packet towards 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 ENCODING: Protobuf
""" """
NEIGHBORINFO_APP: PortNum.ValueType # 71 NEIGHBORINFO_APP: PortNum.ValueType # 71

View File

File diff suppressed because one or more lines are too long

View File

@@ -127,6 +127,22 @@ class _TelemetrySensorTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wra
""" """
NAU7802 Scale Chip or compatible NAU7802 Scale Chip or compatible
""" """
BMP3XX: _TelemetrySensorType.ValueType # 26
"""
BMP3XX High accuracy temperature and pressure
"""
ICM20948: _TelemetrySensorType.ValueType # 27
"""
ICM-20948 9-Axis digital motion processor
"""
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
"""
class TelemetrySensorType(_TelemetrySensorType, metaclass=_TelemetrySensorTypeEnumTypeWrapper): class TelemetrySensorType(_TelemetrySensorType, metaclass=_TelemetrySensorTypeEnumTypeWrapper):
""" """
@@ -237,6 +253,22 @@ NAU7802: TelemetrySensorType.ValueType # 25
""" """
NAU7802 Scale Chip or compatible NAU7802 Scale Chip or compatible
""" """
BMP3XX: TelemetrySensorType.ValueType # 26
"""
BMP3XX High accuracy temperature and pressure
"""
ICM20948: TelemetrySensorType.ValueType # 27
"""
ICM-20948 9-Axis digital motion processor
"""
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
"""
global___TelemetrySensorType = TelemetrySensorType global___TelemetrySensorType = TelemetrySensorType
@typing.final @typing.final
@@ -275,13 +307,24 @@ class DeviceMetrics(google.protobuf.message.Message):
def __init__( def __init__(
self, self,
*, *,
battery_level: builtins.int = ..., battery_level: builtins.int | None = ...,
voltage: builtins.float = ..., voltage: builtins.float | None = ...,
channel_utilization: builtins.float = ..., channel_utilization: builtins.float | None = ...,
air_util_tx: builtins.float = ..., air_util_tx: builtins.float | None = ...,
uptime_seconds: builtins.int = ..., uptime_seconds: builtins.int | None = ...,
) -> 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 global___DeviceMetrics = DeviceMetrics
@@ -383,25 +426,60 @@ class EnvironmentMetrics(google.protobuf.message.Message):
def __init__( def __init__(
self, self,
*, *,
temperature: builtins.float = ..., temperature: builtins.float | None = ...,
relative_humidity: builtins.float = ..., relative_humidity: builtins.float | None = ...,
barometric_pressure: builtins.float = ..., barometric_pressure: builtins.float | None = ...,
gas_resistance: builtins.float = ..., gas_resistance: builtins.float | None = ...,
voltage: builtins.float = ..., voltage: builtins.float | None = ...,
current: builtins.float = ..., current: builtins.float | None = ...,
iaq: builtins.int = ..., iaq: builtins.int | None = ...,
distance: builtins.float = ..., distance: builtins.float | None = ...,
lux: builtins.float = ..., lux: builtins.float | None = ...,
white_lux: builtins.float = ..., white_lux: builtins.float | None = ...,
ir_lux: builtins.float = ..., ir_lux: builtins.float | None = ...,
uv_lux: builtins.float = ..., uv_lux: builtins.float | None = ...,
wind_direction: builtins.int = ..., wind_direction: builtins.int | None = ...,
wind_speed: builtins.float = ..., wind_speed: builtins.float | None = ...,
weight: builtins.float = ..., weight: builtins.float | None = ...,
wind_gust: builtins.float = ..., wind_gust: builtins.float | None = ...,
wind_lull: builtins.float = ..., wind_lull: builtins.float | None = ...,
) -> 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", "_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", "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", "_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", "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["_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 global___EnvironmentMetrics = EnvironmentMetrics
@@ -446,14 +524,27 @@ class PowerMetrics(google.protobuf.message.Message):
def __init__( def __init__(
self, self,
*, *,
ch1_voltage: builtins.float = ..., ch1_voltage: builtins.float | None = ...,
ch1_current: builtins.float = ..., ch1_current: builtins.float | None = ...,
ch2_voltage: builtins.float = ..., ch2_voltage: builtins.float | None = ...,
ch2_current: builtins.float = ..., ch2_current: builtins.float | None = ...,
ch3_voltage: builtins.float = ..., ch3_voltage: builtins.float | None = ...,
ch3_current: builtins.float = ..., ch3_current: builtins.float | None = ...,
) -> 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 global___PowerMetrics = PowerMetrics
@@ -528,23 +619,112 @@ class AirQualityMetrics(google.protobuf.message.Message):
def __init__( def __init__(
self, self,
*, *,
pm10_standard: builtins.int = ..., pm10_standard: builtins.int | None = ...,
pm25_standard: builtins.int = ..., pm25_standard: builtins.int | None = ...,
pm100_standard: builtins.int = ..., pm100_standard: builtins.int | None = ...,
pm10_environmental: builtins.int = ..., pm10_environmental: builtins.int | None = ...,
pm25_environmental: builtins.int = ..., pm25_environmental: builtins.int | None = ...,
pm100_environmental: builtins.int = ..., pm100_environmental: builtins.int | None = ...,
particles_03um: builtins.int = ..., particles_03um: builtins.int | None = ...,
particles_05um: builtins.int = ..., particles_05um: builtins.int | None = ...,
particles_10um: builtins.int = ..., particles_10um: builtins.int | None = ...,
particles_25um: builtins.int = ..., particles_25um: builtins.int | None = ...,
particles_50um: builtins.int = ..., particles_50um: builtins.int | None = ...,
particles_100um: builtins.int = ..., particles_100um: builtins.int | None = ...,
) -> 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["_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", "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["_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", "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["_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 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
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 good
"""
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
"""
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 = ...,
) -> 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_total_nodes", b"num_total_nodes", "uptime_seconds", b"uptime_seconds"]) -> None: ...
global___LocalStats = LocalStats
@typing.final @typing.final
class Telemetry(google.protobuf.message.Message): class Telemetry(google.protobuf.message.Message):
""" """
@@ -558,6 +738,7 @@ class Telemetry(google.protobuf.message.Message):
ENVIRONMENT_METRICS_FIELD_NUMBER: builtins.int ENVIRONMENT_METRICS_FIELD_NUMBER: builtins.int
AIR_QUALITY_METRICS_FIELD_NUMBER: builtins.int AIR_QUALITY_METRICS_FIELD_NUMBER: builtins.int
POWER_METRICS_FIELD_NUMBER: builtins.int POWER_METRICS_FIELD_NUMBER: builtins.int
LOCAL_STATS_FIELD_NUMBER: builtins.int
time: builtins.int time: builtins.int
""" """
Seconds since 1970 - or 0 for unknown/unset Seconds since 1970 - or 0 for unknown/unset
@@ -586,6 +767,12 @@ class Telemetry(google.protobuf.message.Message):
Power Metrics Power Metrics
""" """
@property
def local_stats(self) -> global___LocalStats:
"""
Local device mesh statistics
"""
def __init__( def __init__(
self, self,
*, *,
@@ -594,10 +781,11 @@ class Telemetry(google.protobuf.message.Message):
environment_metrics: global___EnvironmentMetrics | None = ..., environment_metrics: global___EnvironmentMetrics | None = ...,
air_quality_metrics: global___AirQualityMetrics | None = ..., air_quality_metrics: global___AirQualityMetrics | None = ...,
power_metrics: global___PowerMetrics | None = ..., power_metrics: global___PowerMetrics | None = ...,
local_stats: global___LocalStats | None = ...,
) -> 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 HasField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_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", "power_metrics", b"power_metrics", "time", b"time", "variant", b"variant"]) -> None: ... def ClearField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_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"] | None: ... def WhichOneof(self, oneof_group: typing.Literal["variant", b"variant"]) -> typing.Literal["device_metrics", "environment_metrics", "air_quality_metrics", "power_metrics", "local_stats"] | None: ...
global___Telemetry = Telemetry global___Telemetry = Telemetry

View File

@@ -1,5 +1,6 @@
""" Serial interface class """ Serial interface class
""" """
# pylint: disable=R0917
import logging import logging
import platform import platform
import time import time

View File

@@ -1,6 +1,7 @@
""" Supported Meshtastic Devices - This is a class and collection of Meshtastic devices. """ 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. 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 # 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 # without installing any libraries that are not currently in the python meshtastic library

View File

@@ -1,11 +1,13 @@
"""TCPInterface class for interfacing with http endpoint """TCPInterface class for interfacing with http endpoint
""" """
# pylint: disable=R0917
import logging import logging
import socket import socket
from typing import Optional from typing import Optional
from meshtastic.stream_interface import StreamInterface from meshtastic.stream_interface import StreamInterface
DEFAULT_TCP_PORT = 4403
class TCPInterface(StreamInterface): class TCPInterface(StreamInterface):
"""Interface class for meshtastic devices over a TCP link""" """Interface class for meshtastic devices over a TCP link"""
@@ -16,7 +18,7 @@ class TCPInterface(StreamInterface):
debugOut=None, debugOut=None,
noProto=False, noProto=False,
connectNow=True, connectNow=True,
portNumber=4403, portNumber=DEFAULT_TCP_PORT,
noNodes:bool=False, noNodes:bool=False,
): ):
"""Constructor, opens a connection to a specified IP address/hostname """Constructor, opens a connection to a specified IP address/hostname

View File

@@ -1,5 +1,5 @@
"""Meshtastic unit tests for __main__.py""" """Meshtastic unit tests for __main__.py"""
# pylint: disable=C0302,W0613 # pylint: disable=C0302,W0613,R0917
import logging import logging
import os import os
@@ -726,8 +726,8 @@ def test_main_sendtext_with_dest(mock_findPorts, mock_serial, mocked_open, mock_
@pytest.mark.unit @pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config") @pytest.mark.usefixtures("reset_mt_config")
def test_main_removeposition_invalid(capsys): def test_main_removeposition_remote(capsys):
"""Test --remove-position with an invalid dest""" """Test --remove-position with a remote dest"""
sys.argv = ["", "--remove-position", "--dest", "!12345678"] sys.argv = ["", "--remove-position", "--dest", "!12345678"]
mt_config.args = sys.argv mt_config.args = sys.argv
iface = MagicMock(autospec=SerialInterface) iface = MagicMock(autospec=SerialInterface)
@@ -735,14 +735,15 @@ def test_main_removeposition_invalid(capsys):
main() main()
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE) 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 == "" assert err == ""
mo.assert_called() mo.assert_called()
@pytest.mark.unit @pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config") @pytest.mark.usefixtures("reset_mt_config")
def test_main_setlat_invalid(capsys): def test_main_setlat_remote(capsys):
"""Test --setlat with an invalid dest""" """Test --setlat with a remote dest"""
sys.argv = ["", "--setlat", "37.5", "--dest", "!12345678"] sys.argv = ["", "--setlat", "37.5", "--dest", "!12345678"]
mt_config.args = sys.argv mt_config.args = sys.argv
iface = MagicMock(autospec=SerialInterface) iface = MagicMock(autospec=SerialInterface)
@@ -750,7 +751,8 @@ def test_main_setlat_invalid(capsys):
main() main()
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE) 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 == "" assert err == ""
mo.assert_called() mo.assert_called()
@@ -769,7 +771,7 @@ def test_main_removeposition(capsys):
mocked_node.removeFixedPosition.side_effect = mock_removeFixedPosition mocked_node.removeFixedPosition.side_effect = mock_removeFixedPosition
iface = MagicMock(autospec=SerialInterface) 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: with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main() main()
@@ -796,7 +798,7 @@ def test_main_setlat(capsys):
mocked_node.setFixedPosition.side_effect = mock_setFixedPosition mocked_node.setFixedPosition.side_effect = mock_setFixedPosition
iface = MagicMock(autospec=SerialInterface) 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: with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main() main()
@@ -825,7 +827,7 @@ def test_main_setlon(capsys):
mocked_node.setFixedPosition.side_effect = mock_setFixedPosition mocked_node.setFixedPosition.side_effect = mock_setFixedPosition
iface = MagicMock(autospec=SerialInterface) 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: with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main() main()
@@ -854,7 +856,7 @@ def test_main_setalt(capsys):
mocked_node.setFixedPosition.side_effect = mock_setFixedPosition mocked_node.setFixedPosition.side_effect = mock_setFixedPosition
iface = MagicMock(autospec=SerialInterface) 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: with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main() main()

View File

@@ -173,7 +173,23 @@ def test_getNode_not_local_timeout(capsys):
assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1 assert pytest_wrapped_e.value.code == 1
out, err = capsys.readouterr() 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 == "" assert err == ""

View File

@@ -231,7 +231,9 @@ def test_node(capsys):
@pytest.mark.unit @pytest.mark.unit
def test_exitSimulator(caplog): def test_exitSimulator(caplog):
"""Test exitSimulator""" """Test exitSimulator"""
anode = Node("foo", "bar", noProto=True) interface = MeshInterface()
interface.nodesByNum = {}
anode = Node(interface, "!ba400000", noProto=True)
with caplog.at_level(logging.DEBUG): with caplog.at_level(logging.DEBUG):
anode.exitSimulator() anode.exitSimulator()
assert re.search(r"in exitSimulator", caplog.text, re.MULTILINE) assert re.search(r"in exitSimulator", caplog.text, re.MULTILINE)
@@ -240,7 +242,9 @@ def test_exitSimulator(caplog):
@pytest.mark.unit @pytest.mark.unit
def test_reboot(caplog): def test_reboot(caplog):
"""Test reboot""" """Test reboot"""
anode = Node(MeshInterface(), 1234567890, noProto=True) interface = MeshInterface()
interface.nodesByNum = {}
anode = Node(interface, 1234567890, noProto=True)
with caplog.at_level(logging.DEBUG): with caplog.at_level(logging.DEBUG):
anode.reboot() anode.reboot()
assert re.search(r"Telling node to reboot", caplog.text, re.MULTILINE) assert re.search(r"Telling node to reboot", caplog.text, re.MULTILINE)
@@ -249,7 +253,9 @@ def test_reboot(caplog):
@pytest.mark.unit @pytest.mark.unit
def test_shutdown(caplog): def test_shutdown(caplog):
"""Test shutdown""" """Test shutdown"""
anode = Node(MeshInterface(), 1234567890, noProto=True) interface = MeshInterface()
interface.nodesByNum = {}
anode = Node(interface, 1234567890, noProto=True)
with caplog.at_level(logging.DEBUG): with caplog.at_level(logging.DEBUG):
anode.shutdown() anode.shutdown()
assert re.search(r"Telling node to shutdown", caplog.text, re.MULTILINE) assert re.search(r"Telling node to shutdown", caplog.text, re.MULTILINE)
@@ -836,6 +842,34 @@ def test_requestChannel_localNode(caplog):
assert re.search(r"Requesting channel 0", caplog.text, re.MULTILINE) assert re.search(r"Requesting channel 0", caplog.text, re.MULTILINE)
assert not re.search(r"from remote node", 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 # @pytest.mark.unit
# def test_onResponseRequestCannedMessagePluginMesagePart1(caplog): # def test_onResponseRequestCannedMessagePluginMesagePart1(caplog):

View File

@@ -1,4 +1,5 @@
"""Meshtastic unit tests for serial_interface.py""" """Meshtastic unit tests for serial_interface.py"""
# pylint: disable=R0917
import re import re
from unittest.mock import mock_open, patch from unittest.mock import mock_open, patch

View File

@@ -594,3 +594,72 @@ def test_roundtrip_snake_to_camel_camel_to_snake(a_string):
value0 = snake_to_camel(a_string=a_string) value0 = snake_to_camel(a_string=a_string)
value1 = camel_to_snake(a_string=value0) value1 = camel_to_snake(a_string=value0)
assert a_string == value1, (a_string, value1) 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'

View File

@@ -82,7 +82,7 @@ def fromStr(valstr):
val = bytes() val = bytes()
elif valstr.startswith("0x"): elif valstr.startswith("0x"):
# if needed convert to string with asBytes.decode('utf-8') # 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:"): elif valstr.startswith("base64:"):
val = base64.b64decode(valstr[7:]) val = base64.b64decode(valstr[7:])
elif valstr.lower() in {"t", "true", "yes"}: elif valstr.lower() in {"t", "true", "yes"}:

2827
poetry.lock generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
[tool.poetry] [tool.poetry]
name = "meshtastic" name = "meshtastic"
version = "2.4.2" version = "2.5.3"
description = "Python API & client shell for talking to Meshtastic devices" description = "Python API & client shell for talking to Meshtastic devices"
authors = ["Meshtastic Developers <contact@meshtastic.org>"] authors = ["Meshtastic Developers <contact@meshtastic.org>"]
license = "GPL-3.0-only" license = "GPL-3.0-only"
readme = "README.md" readme = "README.md"
[tool.poetry.dependencies] [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" pyserial = "^3.5"
protobuf = ">=5.26.0" protobuf = ">=5.26.0"
dotmap = "^1.3.30" dotmap = "^1.3.30"
@@ -19,13 +19,14 @@ requests = "^2.31.0"
pyparsing = "^3.1.2" pyparsing = "^3.1.2"
pyyaml = "^6.0.1" pyyaml = "^6.0.1"
pypubsub = "^4.0.3" pypubsub = "^4.0.3"
bleak = "^0.21.1" bleak = "^0.22.3"
packaging = "^24.0" packaging = "^24.0"
print-color = "^0.4.6" print-color = "^0.4.6"
dash = { version = "^2.17.1", optional = true } dash = { version = "^2.17.1", optional = true }
pytap2 = { version = "^2.3.0", optional = true } pytap2 = { version = "^2.3.0", optional = true }
dash-bootstrap-components = { version = "^1.6.0", optional = true } dash-bootstrap-components = { version = "^1.6.0", optional = true }
pandas = { version = "^2.2.2", optional = true } pandas = { version = "^2.2.2", optional = true }
pandas-stubs = { version = "^2.2.2.240603", optional = true }
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
hypothesis = "^6.103.2" hypothesis = "^6.103.2"
@@ -43,7 +44,6 @@ types-requests = "^2.31.0.20240406"
types-setuptools = "^69.5.0.20240423" types-setuptools = "^69.5.0.20240423"
types-pyyaml = "^6.0.12.20240311" types-pyyaml = "^6.0.12.20240311"
pyarrow-stubs = "^10.0.1.7" pyarrow-stubs = "^10.0.1.7"
pandas-stubs = "^2.2.2.240603"
[tool.poetry.group.powermon] [tool.poetry.group.powermon]
optional = true optional = true