Compare commits

..

91 Commits
2.6.0 ... 2.7.2

Author SHA1 Message Date
github-actions
e5159f1156 bump version to 2.7.2 2025-09-12 16:49:34 +00:00
Ian McEwen
593b05dbcd protobufs: v2.7.8 2025-09-12 09:46:52 -07:00
Ian McEwen
f519d1f2d2 Merge pull request #818 from pdxlocations/check-module-bitmask
Fix Getting and Setting Excluded Modules: Ringtone and Canned Messages
2025-09-12 09:44:29 -07:00
Ian McEwen
8b36561406 Merge pull request #821 from shukari/contributionHelp
Added Github CONTRIBUTING.md file
2025-09-12 09:43:30 -07:00
shukari
e2b4948d45 Github CONTRIBUTING.md file 2025-09-09 18:17:29 +02:00
pdxlocations
7e3d347b63 remove trailing whitespaces 2025-08-29 23:19:22 -07:00
pdxlocations
c6efccdbd2 init 2025-08-29 23:11:26 -07:00
Ian McEwen
2b10459db0 remove dangling submodule 2025-08-20 10:13:27 -07:00
github-actions
d53ced216c bump version to 2.7.1 2025-08-18 19:40:36 +00:00
Ian McEwen
f5ecd28705 protobufs: v2.7.5 2025-08-18 09:52:48 -07:00
Ian McEwen
82ad9b2f51 Merge pull request #813 from pdxlocations/unmess-unmessageable
Fix --set-owner by calling setOwner!
2025-08-18 09:50:28 -07:00
pdxlocations
03aaa4c98e always call setOwner 2025-08-06 21:58:42 -07:00
github-actions
d7d9c7219a bump version to 2.7.0 2025-08-01 22:56:21 +00:00
Ian McEwen
c60b5d4b05 Add some extra fields that now appear in MyNodeInfo to tests 2025-08-01 15:53:13 -07:00
Ian McEwen
83d82c518a Merge pull request #807 from pdxlocations/export-true-defaults
Export missing defaults when set False
2025-08-01 15:51:05 -07:00
Ian McEwen
8a95ce4636 protobufs: v2.7.4 2025-08-01 15:48:32 -07:00
pdxlocations
0261313fc5 add test 2025-07-27 12:10:05 -07:00
pdxlocations
c1a6234694 make tuple type hint explicit 2025-07-26 23:16:50 -07:00
pdxlocations
66e32f812a fix launch.json punctuation 2025-07-26 22:35:18 -07:00
pdxlocations
eb85439000 rename function 2025-07-26 22:27:10 -07:00
pdxlocations
885eb4898d init 2025-07-26 22:20:19 -07:00
Ian McEwen
172c123990 protobufs: v2.7.3 2025-07-22 17:26:15 -07:00
Ian McEwen
fcdd83838b Merge pull request #795 from pdxlocations/canned-config
Add Ringtone and Canned Messages to --export-config and --configure
2025-07-22 17:22:11 -07:00
Ian McEwen
58967e1d91 Merge pull request #794 from pdxlocations/is-unmessageable
add --set-is-unmessageable to CLI commands
2025-07-22 17:07:50 -07:00
pdxlocations
17f7e8e20e don't check for typoed keyword 2025-07-22 11:23:45 -07:00
pdxlocations
9b5a889676 combine arguments 2025-07-22 10:17:40 -07:00
pdxlocations
ce7c61861f Merge branch 'master' into is-unmessageable 2025-07-22 10:15:19 -07:00
Ian McEwen
4adcbb6787 Merge pull request #743 from ianmcorvidae/client-notifications
Add handling of clientNotification on FromRadio
2025-07-22 09:55:19 -07:00
Ian McEwen
125f63419e Merge branch 'master' into client-notifications 2025-07-22 09:54:17 -07:00
Ian McEwen
cad5d18aff Merge pull request #798 from pdxlocations/export-utf8
Allow forced UTF-8 encoding for --export-config
2025-07-22 09:28:14 -07:00
Ian McEwen
706d0649c1 Merge pull request #801 from Cyclic3/master
Plumb reply_id into sendText and sendData
2025-07-22 09:23:02 -07:00
Ian McEwen
167044907d for some reason pylint likes this better 2025-07-16 19:16:16 -07:00
Ian McEwen
ab1669994f Merge pull request #804 from dangerdyke/fix-vids
Add seeed xiao esp32s3 support
2025-07-16 18:44:16 -07:00
Tom Fifield
6f67f33378 Merge pull request #806 from meshtastic/fifieldt-patch-1
Add check for poetry install to regen-protobufs.sh
2025-07-17 09:05:17 +08:00
Tom Fifield
e60c8ea105 Add check for poetry install to regen-protobufs.sh
This was failing in the CI because the poetry was not initialized.
2025-07-17 10:49:23 +10:00
flockofsparrows
d633f8c895 Add seeed xiao esp32s3 to supported devices 2025-07-09 16:23:21 -04:00
Cyclic3
ca82e1ce2b plumb reply_id into sendText and sendData 2025-07-08 23:38:02 +01:00
pdxlocations
0ae23eec7e don't think i needed that 2025-06-30 00:34:44 -07:00
pdxlocations
2fa85bac1f typo 2025-06-30 00:21:15 -07:00
pdxlocations
58fc614fb7 fix test 2025-06-30 00:12:42 -07:00
pdxlocations
795b652069 export utf-8 2025-06-30 00:03:11 -07:00
rcarteraz
213faa0cae rename and move license file 2025-06-25 12:23:00 -07:00
pdxlocations
68a2009e0e add more tests 2025-06-24 11:47:33 -07:00
pdxlocations
c76e4dac87 undo comment 2025-06-24 11:17:01 -07:00
pdxlocations
428be9fbce add mesh_interface tests 2025-06-24 11:16:23 -07:00
pdxlocations
d83f7b2307 add to example config 2025-06-24 10:12:12 -07:00
pdxlocations
eb453a2e8a add to tests 2025-06-24 08:16:45 -07:00
pdxlocations
308ac93399 add to configure 2025-06-24 07:40:11 -07:00
pdxlocations
84417f0bb1 working export-config 2025-06-23 22:39:24 -07:00
pdxlocations
0bb3389b3b init 2025-06-23 22:11:50 -07:00
pdxlocations
22b3062151 remove whitespace 2025-06-23 16:37:49 -07:00
pdxlocations
373b8a3139 combine with set_owner handling 2025-06-23 16:14:59 -07:00
github-actions
db21942244 bump version to 2.6.4 2025-06-23 22:15:45 +00:00
Ian McEwen
c55f1ef610 Merge pull request #782 from Crank-Git/validate-short-and-long-names
Add validation/prevent --set-owner, --set-owner-short, and --set-ham from accepting empty or whitespace-only names
2025-06-23 09:15:47 -07:00
pdxlocations
51b543ff40 add tests 2025-06-21 18:16:24 -07:00
pdxlocations
8752a0de6e remove whitespace 2025-06-21 16:25:48 -07:00
pdxlocations
7160e79fbf more not incorrect spelling 2025-06-21 13:51:58 -07:00
pdxlocations
b73fcbff88 didn't spell it wrong 2025-06-21 13:50:30 -07:00
pdxlocations
1b5b07e752 add --set-is-unmessageable 2025-06-21 13:44:25 -07:00
Ian McEwen
ab997aac84 Merge pull request #790 from ianmcorvidae/sendMqttClientProxyMessage
Add a sendMqttClientProxyMessage helper for client proxy implementation
2025-06-16 12:48:47 -07:00
Ian McEwen
a097161dbc Add a sendMqttClientProxyMessage helper for client proxy implementation 2025-06-16 12:45:25 -07:00
Ian McEwen
e6750507c8 protobufs: v2.6.12 2025-06-16 12:22:31 -07:00
Ian McEwen
0deb98b4c6 Merge pull request #785 from grleblanc/master
fix(util): update waitForTraceRoute reset logic
2025-06-09 16:22:45 -07:00
grleblanc
04a0ff6322 fix(util): fix typo 2025-06-09 15:50:21 -04:00
grleblanc
b4764d3bc3 fix(util): update waitForTraceRoute reset logic 2025-06-09 15:05:53 -04:00
Ian McEwen
9281c4a335 Correctly call self.close() in disconnected_callback for bleak (fixes #770) 2025-06-09 11:52:23 -07:00
Ben Meadors
3c2dd6f4ff Merge pull request #783 from pdxlocations/config-work
Fix --configure by adding delays after sections
2025-06-09 05:37:25 -05:00
pdxlocations
8e48d141c8 add sleeps 2025-06-08 23:32:32 -07:00
Crank-Git
8a6ee5fb35 fixed assertion errors by replace ham id with ham radio callsign, fixed _sendAdmin assertion 2025-06-08 20:39:26 -04:00
Crank-Git
aa786c7ebd Fix linting errors and duplicate function 2025-06-08 19:51:21 -04:00
Crank-Git
23be2d2189 Add validation/prevent --set-owner, --set-owner-short, and --set-ham from accepting empty or whitespace-only names. This is in relation to meshtastic#6867 firmware feature request https://github.com/meshtastic/firmware/issues/6867 2025-06-08 18:16:49 -04:00
Ian McEwen
622a435465 Add __repr__ methods to interface types and Node, for nicer printing/logging 2025-05-08 21:23:00 -07:00
github-actions
56680f8da6 bump version to 2.6.3 2025-05-08 22:27:56 +00:00
Ian McEwen
321a960c13 protobufs: v2.6.7 2025-05-08 15:26:47 -07:00
Ian McEwen
4668852b0b Admin messages should be requesting acknowledgements 2025-05-08 15:22:27 -07:00
github-actions
c3973117c8 bump version to 2.6.2 2025-04-23 16:49:59 +00:00
Ian McEwen
d456e4ce30 protobufs: v2.6.6 2025-04-23 09:47:13 -07:00
Ben Meadors
ec78f62992 Merge pull request #763 from meshtastic/revert-753-fix-rtsdtr-windows
Revert "Work around RTS/DTR serial reset issues on Windows"
2025-04-15 16:37:23 -05:00
Ben Meadors
dfc9547ffc Revert "Work around RTS/DTR serial reset issues on Windows" 2025-04-15 16:03:33 -05:00
Ian McEwen
ee0f73a20e Merge pull request #761 from derekn/master
fixing tcp_interface 100% cpu usage bug (#709)
2025-04-15 13:56:28 -07:00
Derek Nicol
2e73fe310c fixing tcp_interface 100% cpu usage bug (#709) 2025-04-15 15:23:09 -05:00
Ian McEwen
d4bc39153a bump to 2.6.2a0 2025-04-05 23:01:43 -07:00
github-actions
2e8f823431 bump version to 2.6.1 2025-04-06 05:56:17 +00:00
Ian McEwen
675169167c protobufs: v2.6.4 2025-04-05 22:53:02 -07:00
Ian McEwen
75f8e27799 Merge pull request #749 from cdanis/fix-default-pytest
Fix pytest test collection on default install
2025-03-30 22:28:28 -07:00
Ian McEwen
f426699d2b Merge pull request #753 from dwhinham/fix-rtsdtr-windows
Work around RTS/DTR serial reset issues on Windows
2025-03-30 22:27:34 -07:00
Dale Whinham
bc1664dade Work around RTS/DTR serial reset issues on Windows
Some devices (e.g. Heltec V3.1) are reset when the RTS or DTR pins are
messed with, which means that without workarounds, Meshtastic CLI will
cause a reset with any operation that opens the serial port.

This behavior is documented in this PySerial issue:
https://github.com/pyserial/pyserial/issues/124

On Linux, we already handle this by disabling the HUPCL termios flag,
which has the effect of preventing the offending lines being toggled. On
Windows, setting the initial state of RTS and DTR before opening the
port has a similar effect.

Implement this workaround so that Meshtastic CLI can be used on Windows
with these devices.
2025-03-20 13:47:25 +00:00
Ian McEwen
32a61b0209 Make nanopb.proto stuff work right again, hopefully 2025-03-12 14:13:43 -07:00
Chris Danis
b42d33824a Fix pytest test collection on default install
As is, with a default `poetry install`, a simple `poetry pytest run`
will encouter import errors while reading the test files themselves --
which causes pytest to fatally error during test collection, meaning no
tests are run.
2025-03-07 13:16:20 -05:00
Ian McEwen
f5fa30cb22 try to get pylint happier 2025-02-20 12:40:39 -07:00
Ian McEwen
46a8db286c Add handling of clientNotification on FromRadio, sending a pubsub message 2025-02-20 12:36:21 -07:00
44 changed files with 2852 additions and 348 deletions

22
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,22 @@
# Contributing to Meshtastic Python
## Development resources
- [API Documentation](https://python.meshtastic.org/)
- [Meshtastic Python Development](https://meshtastic.org/docs/development/python/)
- [Building Meshtastic Python](https://meshtastic.org/docs/development/python/building/)
- [Using the Meshtastic Python Library](https://meshtastic.org/docs/development/python/library/)
## How to check your code (pytest/pylint) before a PR
- [Pre-requisites](https://meshtastic.org/docs/development/python/building/#pre-requisites)
- also execute `poetry install --all-extras --with dev,powermon` for all optional dependencies
- check your code with github ci actions locally
- You need to have act installed. You can get it at https://nektosact.com/
- on linux: `act -P ubuntu-latest=-self-hosted --matrix "python-version:3.12"`
- on windows:
- linux checks (linux docker): `act --matrix "python-version:3.12"`
- windows checks (windows host): `act -P ubuntu-latest=-self-hosted --matrix "python-version:3.12"`
- or run all locally:
- run `poetry run pylint meshtastic examples/ --ignore-patterns ".*_pb2.pyi?$"`
- run `poetry run mypy meshtastic/`
- run `poetry run pytest`
- more commands see [CI workflow](https://github.com/meshtastic/python/blob/master/.github/workflows/ci.yml)

12
.vscode/launch.json vendored
View File

@@ -4,6 +4,7 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "meshtastic BLE",
"type": "debugpy",
@@ -261,7 +262,14 @@
"module": "meshtastic",
"justMyCode": true,
"args": ["--nodes", "--show-fields", "AKA,Pubkey,Role,Role,Role,Latitude,Latitude,deviceMetrics.voltage"]
}
},
{
"name": "meshtastic --export-config",
"type": "debugpy",
"request": "launch",
"module": "meshtastic",
"justMyCode": true,
"args": ["--export-config", "config.json"]
},
]
}

View File

View File

@@ -6,6 +6,12 @@ set -e
#gsed -i 's/import "\//import ".\//g' ./protobufs/meshtastic/*
#gsed -i 's/package meshtastic;//g' ./protobufs/meshtastic/*
POETRYDIR=$(poetry env info --path)
if [[ -z "${POETRYDIR}" ]]; then
poetry install
fi
# protoc looks for mypy plugin in the python path
source $(poetry env info --path)/bin/activate
@@ -22,6 +28,7 @@ OUTDIR=${TMPDIR}/out
PYIDIR=${TMPDIR}/out
mkdir -p "${OUTDIR}" "${INDIR}" "${PYIDIR}"
cp ./protobufs/meshtastic/*.proto "${INDIR}"
cp ./protobufs/nanopb.proto "${INDIR}"
# OS-X sed is apparently a little different and expects an arg for -i
if [[ $OSTYPE == 'darwin'* ]]; then
@@ -36,6 +43,8 @@ $SEDCMD 's/^package meshtastic;/package meshtastic.protobuf;/' "${INDIR}/"*.prot
# fix the imports to match
$SEDCMD 's/^import "meshtastic\//import "meshtastic\/protobuf\//' "${INDIR}/"*.proto
$SEDCMD 's/^import "nanopb.proto"/import "meshtastic\/protobuf\/nanopb.proto"/' "${INDIR}/"*.proto
# Generate the python files
./nanopb-0.4.8/generator-bin/protoc -I=$TMPDIR/in --python_out "${OUTDIR}" "--mypy_out=${PYIDIR}" $INDIR/*.proto

View File

@@ -4,6 +4,9 @@ owner_short: BOB
channel_url: https://www.meshtastic.org/e/#CgMSAQESCDgBQANIAVAe
canned_messages: Hi|Bye|Yes|No|Ok
ringtone: 24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p
location:
lat: 35.88888
lon: -93.88888

View File

@@ -35,6 +35,7 @@ type of packet, you should subscribe to the full topic name. If you want to see
- `meshtastic.receive.data.portnum(packet)` (where portnum is an integer or well known PortNum enum)
- `meshtastic.node.updated(node = NodeInfo)` - published when a node in the DB changes (appears, location changed, username changed, etc...)
- `meshtastic.log.line(line)` - a raw unparsed log line from the radio
- `meshtastic.clientNotification(notification, interface) - a ClientNotification sent from the radio
We receive position, user, or data packets from the mesh. You probably only care about `meshtastic.receive.data`. The first argument for
that publish will be the packet. Text or binary data packets (from `sendData` or `sendText`) will both arrive this way. If you print packet

View File

@@ -3,7 +3,7 @@
# We just hit the 1600 line limit for main.py, but I currently have a huge set of powermon/structured logging changes
# later we can have a separate changelist to refactor main.py into smaller files
# pylint: disable=too-many-lines
# pylint: disable=R0917,C0302
from typing import List, Optional, Union
from types import ModuleType
@@ -59,7 +59,7 @@ except ImportError as e:
have_powermon = False
powermon_exception = e
meter = None
from meshtastic.protobuf import channel_pb2, config_pb2, portnums_pb2
from meshtastic.protobuf import channel_pb2, config_pb2, portnums_pb2, mesh_pb2
from meshtastic.version import get_active_version
def onReceive(packet, interface) -> None:
@@ -339,32 +339,60 @@ def onConnected(interface):
# can include lat/long/alt etc: latitude = 37.5, longitude = -122.1
interface.getNode(args.dest, False, **getNode_kwargs).setFixedPosition(lat, lon, alt)
if args.set_owner or args.set_owner_short:
if args.set_owner or args.set_owner_short or args.set_is_unmessageable:
closeNow = True
waitForAckNak = True
if args.set_owner and args.set_owner_short:
print(f"Setting device owner to {args.set_owner} and short name to {args.set_owner_short}")
elif args.set_owner:
print(f"Setting device owner to {args.set_owner}")
else: # short name only
print(f"Setting device owner short to {args.set_owner_short}")
interface.getNode(args.dest, False, **getNode_kwargs).setOwner(long_name=args.set_owner, short_name=args.set_owner_short)
# TODO: add to export-config and configure
long_name = args.set_owner.strip() if args.set_owner else None
short_name = args.set_owner_short.strip() if args.set_owner_short else None
if long_name is not None and not long_name:
meshtastic.util.our_exit("ERROR: Long Name cannot be empty or contain only whitespace characters")
if short_name is not None and not short_name:
meshtastic.util.our_exit("ERROR: Short Name cannot be empty or contain only whitespace characters")
if long_name and short_name:
print(f"Setting device owner to {long_name} and short name to {short_name}")
elif long_name:
print(f"Setting device owner to {long_name}")
elif short_name:
print(f"Setting device owner short to {short_name}")
unmessagable = None
if args.set_is_unmessageable is not None:
unmessagable = (
meshtastic.util.fromStr(args.set_is_unmessageable)
if isinstance(args.set_is_unmessageable, str)
else args.set_is_unmessageable
)
print(f"Setting device owner is_unmessageable to {unmessagable}")
interface.getNode(args.dest, False, **getNode_kwargs).setOwner(
long_name=long_name,
short_name=short_name,
is_unmessagable=unmessagable
)
if args.set_canned_message:
closeNow = True
waitForAckNak = True
print(f"Setting canned plugin message to {args.set_canned_message}")
interface.getNode(args.dest, False, **getNode_kwargs).set_canned_message(
args.set_canned_message
)
node = interface.getNode(args.dest, False, **getNode_kwargs)
if node.module_available(mesh_pb2.CANNEDMSG_CONFIG):
print(f"Setting canned plugin message to {args.set_canned_message}")
node.set_canned_message(args.set_canned_message)
else:
print("Canned Message module is excluded by firmware; skipping set.")
# TODO: add to export-config and configure
if args.set_ringtone:
closeNow = True
waitForAckNak = True
print(f"Setting ringtone to {args.set_ringtone}")
interface.getNode(args.dest, False, **getNode_kwargs).set_ringtone(args.set_ringtone)
node = interface.getNode(args.dest, False, **getNode_kwargs)
if node.module_available(mesh_pb2.EXTNOTIF_CONFIG):
print(f"Setting ringtone to {args.set_ringtone}")
node.set_ringtone(args.set_ringtone)
else:
print("External Notification is excluded by firmware; skipping ringtone set.")
if args.pos_fields:
# If --pos-fields invoked with args, set position fields
@@ -402,6 +430,8 @@ def onConnected(interface):
print(" ".join(fieldNames))
if args.set_ham:
if not args.set_ham.strip():
meshtastic.util.our_exit("ERROR: Ham radio callsign cannot be empty or contain only whitespace characters")
closeNow = True
print(f"Setting Ham ID to {args.set_ham} and turning off encryption")
interface.getNode(args.dest, **getNode_kwargs).setOwner(args.set_ham, is_licensed=True)
@@ -644,11 +674,20 @@ def onConnected(interface):
interface.getNode(args.dest, False, **getNode_kwargs).beginSettingsTransaction()
if "owner" in configuration:
# Validate owner name before setting
owner_name = str(configuration["owner"]).strip()
if not owner_name:
meshtastic.util.our_exit("ERROR: Long Name cannot be empty or contain only whitespace characters")
print(f"Setting device owner to {configuration['owner']}")
waitForAckNak = True
interface.getNode(args.dest, False, **getNode_kwargs).setOwner(configuration["owner"])
time.sleep(0.5)
if "owner_short" in configuration:
# Validate owner short name before setting
owner_short_name = str(configuration["owner_short"]).strip()
if not owner_short_name:
meshtastic.util.our_exit("ERROR: Short Name cannot be empty or contain only whitespace characters")
print(
f"Setting device owner short to {configuration['owner_short']}"
)
@@ -656,8 +695,13 @@ def onConnected(interface):
interface.getNode(args.dest, False, **getNode_kwargs).setOwner(
long_name=None, short_name=configuration["owner_short"]
)
time.sleep(0.5)
if "ownerShort" in configuration:
# Validate owner short name before setting
owner_short_name = str(configuration["ownerShort"]).strip()
if not owner_short_name:
meshtastic.util.our_exit("ERROR: Short Name cannot be empty or contain only whitespace characters")
print(
f"Setting device owner short to {configuration['ownerShort']}"
)
@@ -665,14 +709,27 @@ def onConnected(interface):
interface.getNode(args.dest, False, **getNode_kwargs).setOwner(
long_name=None, short_name=configuration["ownerShort"]
)
time.sleep(0.5)
if "channel_url" in configuration:
print("Setting channel url to", configuration["channel_url"])
interface.getNode(args.dest, **getNode_kwargs).setURL(configuration["channel_url"])
time.sleep(0.5)
if "channelUrl" in configuration:
print("Setting channel url to", configuration["channelUrl"])
interface.getNode(args.dest, **getNode_kwargs).setURL(configuration["channelUrl"])
time.sleep(0.5)
if "canned_messages" in configuration:
print("Setting canned message messages to", configuration["canned_messages"])
interface.getNode(args.dest, **getNode_kwargs).set_canned_message(configuration["canned_messages"])
time.sleep(0.5)
if "ringtone" in configuration:
print("Setting ringtone to", configuration["ringtone"])
interface.getNode(args.dest, **getNode_kwargs).set_ringtone(configuration["ringtone"])
time.sleep(0.5)
if "location" in configuration:
alt = 0
@@ -691,6 +748,7 @@ def onConnected(interface):
print(f"Fixing longitude at {lon} degrees")
print("Setting device position")
interface.localNode.setFixedPosition(lat, lon, alt)
time.sleep(0.5)
if "config" in configuration:
localConfig = interface.getNode(args.dest, **getNode_kwargs).localConfig
@@ -701,6 +759,7 @@ def onConnected(interface):
interface.getNode(args.dest, **getNode_kwargs).writeConfig(
meshtastic.util.camel_to_snake(section)
)
time.sleep(0.5)
if "module_config" in configuration:
moduleConfig = interface.getNode(args.dest, **getNode_kwargs).moduleConfig
@@ -713,6 +772,7 @@ def onConnected(interface):
interface.getNode(args.dest, **getNode_kwargs).writeConfig(
meshtastic.util.camel_to_snake(section)
)
time.sleep(0.5)
interface.getNode(args.dest, False, **getNode_kwargs).commitSettingsTransaction()
print("Writing modified configuration to device")
@@ -721,9 +781,20 @@ def onConnected(interface):
if args.dest != BROADCAST_ADDR:
print("Exporting configuration of remote nodes is not supported.")
return
# export the configuration (the opposite of '--configure')
closeNow = True
export_config(interface)
config_txt = export_config(interface)
if args.export_config == "-":
# Output to stdout (preserves legacy use of `> file.yaml`)
print(config_txt)
else:
try:
with open(args.export_config, "w", encoding="utf-8") as f:
f.write(config_txt)
print(f"Exported configuration to {args.export_config}")
except Exception as e:
meshtastic.util.our_exit(f"ERROR: Failed to write config file: {e}")
if args.ch_set_url:
closeNow = True
@@ -894,12 +965,14 @@ def onConnected(interface):
if args.get_canned_message:
closeNow = True
print("")
interface.getNode(args.dest, **getNode_kwargs).get_canned_message()
messages = interface.getNode(args.dest, **getNode_kwargs).get_canned_message()
print(f"canned_plugin_message:{messages}")
if args.get_ringtone:
closeNow = True
print("")
interface.getNode(args.dest, **getNode_kwargs).get_ringtone()
ringtone = interface.getNode(args.dest, **getNode_kwargs).get_ringtone()
print(f"ringtone:{ringtone}")
if args.info:
print("")
@@ -1054,15 +1127,38 @@ def subscribe() -> None:
# pub.subscribe(onNode, "meshtastic.node")
def set_missing_flags_false(config_dict: dict, true_defaults: set[tuple[str, str]]) -> None:
"""Ensure that missing default=True keys are present in the config_dict and set to False."""
for path in true_defaults:
d = config_dict
for key in path[:-1]:
if key not in d or not isinstance(d[key], dict):
d[key] = {}
d = d[key]
if path[-1] not in d:
d[path[-1]] = False
def export_config(interface) -> str:
"""used in --export-config"""
configObj = {}
# A list of configuration keys that should be set to False if they are missing
true_defaults = {
("bluetooth", "enabled"),
("lora", "sx126xRxBoostedGain"),
("lora", "txEnabled"),
("lora", "usePreset"),
("position", "positionBroadcastSmartEnabled"),
("security", "serialEnabled"),
("mqtt", "encryptionEnabled"),
}
owner = interface.getLongName()
owner_short = interface.getShortName()
channel_url = interface.localNode.getURL()
myinfo = interface.getMyNodeInfo()
canned_messages = interface.getCannedMessage()
ringtone = interface.getRingtone()
pos = myinfo.get("position")
lat = None
lon = None
@@ -1081,6 +1177,10 @@ def export_config(interface) -> str:
configObj["channelUrl"] = channel_url
else:
configObj["channel_url"] = channel_url
if canned_messages:
configObj["canned_messages"] = canned_messages
if ringtone:
configObj["ringtone"] = ringtone
# lat and lon don't make much sense without the other (so fill with 0s), and alt isn't meaningful without both
if lat or lon:
configObj["location"] = {"lat": lat or float(0), "lon": lon or float(0)}
@@ -1088,6 +1188,7 @@ def export_config(interface) -> str:
configObj["location"]["alt"] = alt
config = MessageToDict(interface.localNode.localConfig) #checkme - Used as a dictionary here and a string below
#was used as a string here and a Dictionary above
if config:
# Convert inner keys to correct snake/camelCase
prefs = {}
@@ -1110,6 +1211,8 @@ def export_config(interface) -> str:
else:
configObj["config"] = config
set_missing_flags_false(configObj["config"], true_defaults)
module_config = MessageToDict(interface.localNode.moduleConfig)
if module_config:
# Convert inner keys to correct snake/camelCase
@@ -1125,7 +1228,6 @@ def export_config(interface) -> str:
config_txt = "# start of Meshtastic configure yaml\n" #checkme - "config" (now changed to config_out)
#was used as a string here and a Dictionary above
config_txt += yaml.dump(configObj)
print(config_txt)
return config_txt
@@ -1182,6 +1284,22 @@ def common():
meshtastic.util.support_info()
meshtastic.util.our_exit("", 0)
# Early validation for owner names before attempting device connection
if hasattr(args, 'set_owner') and args.set_owner is not None:
stripped_long_name = args.set_owner.strip()
if not stripped_long_name:
meshtastic.util.our_exit("ERROR: Long Name cannot be empty or contain only whitespace characters")
if hasattr(args, 'set_owner_short') and args.set_owner_short is not None:
stripped_short_name = args.set_owner_short.strip()
if not stripped_short_name:
meshtastic.util.our_exit("ERROR: Short Name cannot be empty or contain only whitespace characters")
if hasattr(args, 'set_ham') and args.set_ham is not None:
stripped_ham_name = args.set_ham.strip()
if not stripped_ham_name:
meshtastic.util.our_exit("ERROR: Ham radio callsign cannot be empty or contain only whitespace characters")
if have_powermon:
create_power_meter()
@@ -1409,8 +1527,10 @@ def addImportExportArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentPar
)
group.add_argument(
"--export-config",
help="Export the configuration in yaml(.yml) format.",
action="store_true",
nargs="?",
const="-", # default to "-" if no value provided
metavar="FILE",
help="Export device config as YAML (to stdout if no file given)"
)
return parser
@@ -1532,6 +1652,11 @@ def addConfigArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
"--set-ham", help="Set licensed Ham ID and turn off encryption", action="store"
)
group.add_argument(
"--set-is-unmessageable", "--set-is-unmessagable",
help="Set if a node is messageable or not", action="store"
)
group.add_argument(
"--ch-set-url", "--seturl",
help="Set all channels and set LoRa config from a supplied URL",

View File

@@ -83,6 +83,17 @@ class BLEInterface(MeshInterface):
# Note: the on disconnected callback will call our self.close which will make us nicely wait for threads to exit
self._exit_handler = atexit.register(self.client.disconnect)
def __repr__(self):
rep = f"BLEInterface(address={self.client.address if self.client else None!r}"
if self.debugOut is not None:
rep += f", debugOut={self.debugOut!r}"
if self.noProto:
rep += ", noProto=True"
if self.noNodes:
rep += ", noNodes=True"
rep += ")"
return rep
def from_num_handler(self, _, b: bytes) -> None: # pylint: disable=C0116
"""Handle callbacks for fromnum notify.
Note: this method does not need to be async because it is just setting a bool.
@@ -163,7 +174,7 @@ class BLEInterface(MeshInterface):
# Bleak docs recommend always doing a scan before connecting (even if we know addr)
device = self.find_device(address)
client = BLEClient(device.address, disconnected_callback=lambda _: self.close)
client = BLEClient(device.address, disconnected_callback=lambda _: self.close())
client.connect()
client.discover()
return client

View File

@@ -1,6 +1,6 @@
"""Mesh Interface class
"""
# pylint: disable=R0917
# pylint: disable=R0917,C0302
import collections
import json
@@ -411,7 +411,8 @@ class MeshInterface: # pylint: disable=R0902
wantResponse: bool = False,
onResponse: Optional[Callable[[dict], Any]] = None,
channelIndex: int = 0,
portNum: portnums_pb2.PortNum.ValueType = portnums_pb2.PortNum.TEXT_MESSAGE_APP
portNum: portnums_pb2.PortNum.ValueType = portnums_pb2.PortNum.TEXT_MESSAGE_APP,
replyId: Optional[int]=None,
):
"""Send a utf8 string to some other node, if the node has a display it
will also be shown on the device.
@@ -428,6 +429,7 @@ class MeshInterface: # pylint: disable=R0902
send an application layer response
portNum -- the application portnum (similar to IP port numbers)
of the destination, see portnums.proto for a list
replyId -- the ID of the message that this packet is a response to
Returns the sent packet. The id field will be populated in this packet
and can be used to track future message acks/naks.
@@ -441,6 +443,7 @@ class MeshInterface: # pylint: disable=R0902
wantResponse=wantResponse,
onResponse=onResponse,
channelIndex=channelIndex,
replyId=replyId
)
@@ -451,7 +454,7 @@ class MeshInterface: # pylint: disable=R0902
onResponse: Optional[Callable[[dict], Any]] = None,
channelIndex: int = 0,
):
"""Send an alert text to some other node. This is similar to a text message,
"""Send an alert text to some other node. This is similar to a text message,
but carries a higher priority and is capable of generating special notifications
on certain clients.
@@ -477,6 +480,18 @@ class MeshInterface: # pylint: disable=R0902
priority=mesh_pb2.MeshPacket.Priority.ALERT
)
def sendMqttClientProxyMessage(self, topic: str, data: bytes):
"""Send an MQTT Client Proxy message to the radio.
Topic and data should be the MQTT topic and the message
payload from an MQTT broker, respectively."""
prox = mesh_pb2.MqttClientProxyMessage()
prox.topic = topic
prox.data = data
toRadio = mesh_pb2.ToRadio()
toRadio.mqttClientProxyMessage.CopyFrom(prox)
self._sendToRadio(toRadio)
def sendData(
self,
data,
@@ -491,6 +506,7 @@ class MeshInterface: # pylint: disable=R0902
pkiEncrypted: Optional[bool]=False,
publicKey: Optional[bytes]=None,
priority: mesh_pb2.MeshPacket.Priority.ValueType=mesh_pb2.MeshPacket.Priority.RELIABLE,
replyId: Optional[int]=None,
): # pylint: disable=R0913
"""Send a data packet to some other node
@@ -515,6 +531,7 @@ class MeshInterface: # pylint: disable=R0902
will implicitly be true.
channelIndex -- channel number to use
hopLimit -- hop limit to use
replyId -- the ID of the message that this packet is a response to
Returns the sent packet. The id field will be populated in this packet
and can be used to track future message acks/naks.
@@ -542,6 +559,8 @@ class MeshInterface: # pylint: disable=R0902
meshPacket.decoded.portnum = portNum
meshPacket.decoded.want_response = wantResponse
meshPacket.id = self._generatePacketId()
if replyId is not None:
meshPacket.decoded.reply_id = replyId
if priority is not None:
meshPacket.priority = priority
@@ -872,7 +891,7 @@ class MeshInterface: # pylint: disable=R0902
Send a waypoint deletion packet to some other node (normally a broadcast)
NB: The id must be the waypoint's id and not the id of the packet creation.
Returns the sent packet. The id field will be populated in this packet and
can be used to track future message acks/naks.
"""
@@ -1065,6 +1084,20 @@ class MeshInterface: # pylint: disable=R0902
return user.get("publicKey", None)
return None
def getCannedMessage(self):
"""Get canned message"""
node = self.localNode
if node is not None:
return node.get_canned_message()
return None
def getRingtone(self):
"""Get ringtone"""
node = self.localNode
if node is not None:
return node.get_ringtone()
return None
def _waitConnected(self, timeout=30.0):
"""Block until the initial node db download is complete, or timeout
and raise an exception"""
@@ -1311,6 +1344,14 @@ class MeshInterface: # pylint: disable=R0902
self._handleLogRecord(fromRadio.log_record)
elif fromRadio.HasField("queueStatus"):
self._handleQueueStatusFromRadio(fromRadio.queueStatus)
elif fromRadio.HasField("clientNotification"):
publishingThread.queueWork(
lambda: pub.sendMessage(
"meshtastic.clientNotification",
notification=fromRadio.clientNotification,
interface=self,
)
)
elif fromRadio.HasField("mqttClientProxyMessage"):
publishingThread.queueWork(

View File

@@ -42,6 +42,25 @@ class Node:
self.gotResponse = None
def __repr__(self):
r = f"Node({self.iface!r}, 0x{self.nodeNum:08x}"
if self.noProto:
r += ", noProto=True"
if self._timeout.expireTimeout != 300:
r += ", timeout={self._timeout.expireTimeout!r}"
r += ")"
return r
def module_available(self, excluded_bit: int) -> bool:
"""Check DeviceMetadata.excluded_modules to see if a module is available."""
meta = getattr(self.iface, "metadata", None)
if meta is None:
return True
try:
return (meta.excluded_modules & excluded_bit) == 0
except Exception:
return True
def showChannels(self):
"""Show human readable description of our channels."""
print("Channels:")
@@ -289,7 +308,7 @@ class Node:
return c.index
return 0
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, is_unmessagable: Optional[bool]=None):
"""Set device owner name"""
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
self.ensureSessionKey()
@@ -298,19 +317,28 @@ class Node:
nChars = 4
if long_name is not None:
long_name = long_name.strip()
# Validate that long_name is not empty or whitespace-only
if not long_name:
our_exit("ERROR: Long Name cannot be empty or contain only whitespace characters")
p.set_owner.long_name = long_name
p.set_owner.is_licensed = is_licensed
if short_name is not None:
short_name = short_name.strip()
# Validate that short_name is not empty or whitespace-only
if not short_name:
our_exit("ERROR: Short Name cannot be empty or contain only whitespace characters")
if len(short_name) > nChars:
short_name = short_name[:nChars]
print(f"Maximum is 4 characters, truncated to {short_name}")
p.set_owner.short_name = short_name
if is_unmessagable is not None:
p.set_owner.is_unmessagable = is_unmessagable
# Note: These debug lines are used in unit tests
logging.debug(f"p.set_owner.long_name:{p.set_owner.long_name}:")
logging.debug(f"p.set_owner.short_name:{p.set_owner.short_name}:")
logging.debug(f"p.set_owner.is_licensed:{p.set_owner.is_licensed}")
logging.debug(f"p.set_owner.is_unmessagable:{p.set_owner.is_unmessagable}:")
# If sending to a remote node, wait for ACK/NAK
if self == self.iface.localNode:
onResponse = None
@@ -423,6 +451,10 @@ class Node:
def get_ringtone(self):
"""Get the ringtone. Concatenate all pieces together and return a single string."""
logging.debug(f"in get_ringtone()")
if not self.module_available(mesh_pb2.EXTNOTIF_CONFIG):
logging.warning("External Notification module not present (excluded by firmware)")
return None
if not self.ringtone:
p1 = admin_pb2.AdminMessage()
p1.get_ringtone_request = True
@@ -439,12 +471,14 @@ class Node:
if self.ringtonePart:
self.ringtone += self.ringtonePart
print(f"ringtone:{self.ringtone}")
logging.debug(f"ringtone:{self.ringtone}")
return self.ringtone
def set_ringtone(self, ringtone):
"""Set the ringtone. The ringtone length must be less than 230 character."""
if not self.module_available(mesh_pb2.EXTNOTIF_CONFIG):
logging.warning("External Notification module not present (excluded by firmware)")
return None
if len(ringtone) > 230:
our_exit("Warning: The ringtone must be less than 230 characters.")
@@ -495,6 +529,9 @@ class Node:
def get_canned_message(self):
"""Get the canned message string. Concatenate all pieces together and return a single string."""
logging.debug(f"in get_canned_message()")
if not self.module_available(mesh_pb2.CANNEDMSG_CONFIG):
logging.warning("Canned Message module not present (excluded by firmware)")
return None
if not self.cannedPluginMessage:
p1 = admin_pb2.AdminMessage()
p1.get_canned_message_module_messages_request = True
@@ -515,12 +552,14 @@ class Node:
if self.cannedPluginMessageMessages:
self.cannedPluginMessage += self.cannedPluginMessageMessages
print(f"canned_plugin_message:{self.cannedPluginMessage}")
logging.debug(f"canned_plugin_message:{self.cannedPluginMessage}")
return self.cannedPluginMessage
def set_canned_message(self, message):
"""Set the canned message. The canned messages length must be less than 200 character."""
if not self.module_available(mesh_pb2.CANNEDMSG_CONFIG):
logging.warning("Canned Message module not present (excluded by firmware)")
return None
if len(message) > 200:
our_exit("Warning: The canned message must be less than 200 characters.")
@@ -983,7 +1022,7 @@ class Node:
p,
self.nodeNum,
portNum=portnums_pb2.PortNum.ADMIN_APP,
wantAck=False,
wantAck=True,
wantResponse=wantResponse,
onResponse=onResponse,
channelIndex=adminIndex,

View File

File diff suppressed because one or more lines are too long

View File

@@ -74,7 +74,9 @@ class AdminMessage(google.protobuf.message.Message):
TODO: REPLACE
"""
SESSIONKEY_CONFIG: AdminMessage._ConfigType.ValueType # 8
""""""
"""
Session key config
"""
DEVICEUI_CONFIG: AdminMessage._ConfigType.ValueType # 9
"""
device-ui config
@@ -118,7 +120,9 @@ class AdminMessage(google.protobuf.message.Message):
TODO: REPLACE
"""
SESSIONKEY_CONFIG: AdminMessage.ConfigType.ValueType # 8
""""""
"""
Session key config
"""
DEVICEUI_CONFIG: AdminMessage.ConfigType.ValueType # 9
"""
device-ui config
@@ -266,6 +270,44 @@ class AdminMessage(google.protobuf.message.Message):
Backup to the SD card
"""
@typing.final
class InputEvent(google.protobuf.message.Message):
"""
Input event message to be sent to the node.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
EVENT_CODE_FIELD_NUMBER: builtins.int
KB_CHAR_FIELD_NUMBER: builtins.int
TOUCH_X_FIELD_NUMBER: builtins.int
TOUCH_Y_FIELD_NUMBER: builtins.int
event_code: builtins.int
"""
The input event code
"""
kb_char: builtins.int
"""
Keyboard character code
"""
touch_x: builtins.int
"""
The touch X coordinate
"""
touch_y: builtins.int
"""
The touch Y coordinate
"""
def __init__(
self,
*,
event_code: builtins.int = ...,
kb_char: builtins.int = ...,
touch_x: builtins.int = ...,
touch_y: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["event_code", b"event_code", "kb_char", b"kb_char", "touch_x", b"touch_x", "touch_y", b"touch_y"]) -> None: ...
SESSION_PASSKEY_FIELD_NUMBER: builtins.int
GET_CHANNEL_REQUEST_FIELD_NUMBER: builtins.int
GET_CHANNEL_RESPONSE_FIELD_NUMBER: builtins.int
@@ -292,6 +334,7 @@ class AdminMessage(google.protobuf.message.Message):
BACKUP_PREFERENCES_FIELD_NUMBER: builtins.int
RESTORE_PREFERENCES_FIELD_NUMBER: builtins.int
REMOVE_BACKUP_PREFERENCES_FIELD_NUMBER: builtins.int
SEND_INPUT_EVENT_FIELD_NUMBER: builtins.int
SET_OWNER_FIELD_NUMBER: builtins.int
SET_CHANNEL_FIELD_NUMBER: builtins.int
SET_CONFIG_FIELD_NUMBER: builtins.int
@@ -311,6 +354,8 @@ class AdminMessage(google.protobuf.message.Message):
REMOVE_IGNORED_NODE_FIELD_NUMBER: builtins.int
BEGIN_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
COMMIT_EDIT_SETTINGS_FIELD_NUMBER: builtins.int
ADD_CONTACT_FIELD_NUMBER: builtins.int
KEY_VERIFICATION_FIELD_NUMBER: builtins.int
FACTORY_RESET_DEVICE_FIELD_NUMBER: builtins.int
REBOOT_OTA_SECONDS_FIELD_NUMBER: builtins.int
EXIT_SIMULATOR_FIELD_NUMBER: builtins.int
@@ -522,6 +567,13 @@ class AdminMessage(google.protobuf.message.Message):
Respond with the mesh's nodes with their available gpio pins for RemoteHardware module use
"""
@property
def send_input_event(self) -> global___AdminMessage.InputEvent:
"""
Send an input event to the node.
This is used to trigger physical input events like button presses, touch events, etc.
"""
@property
def set_owner(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
@@ -568,6 +620,18 @@ class AdminMessage(google.protobuf.message.Message):
Tell the node to store UI data persistently.
"""
@property
def add_contact(self) -> global___SharedContact:
"""
Add a contact (User) to the nodedb
"""
@property
def key_verification(self) -> global___KeyVerificationAdmin:
"""
Initiate or respond to a key verification request
"""
def __init__(
self,
*,
@@ -597,6 +661,7 @@ class AdminMessage(google.protobuf.message.Message):
backup_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
restore_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
remove_backup_preferences: global___AdminMessage.BackupLocation.ValueType = ...,
send_input_event: global___AdminMessage.InputEvent | None = ...,
set_owner: meshtastic.protobuf.mesh_pb2.User | None = ...,
set_channel: meshtastic.protobuf.channel_pb2.Channel | None = ...,
set_config: meshtastic.protobuf.config_pb2.Config | None = ...,
@@ -616,6 +681,8 @@ class AdminMessage(google.protobuf.message.Message):
remove_ignored_node: builtins.int = ...,
begin_edit_settings: builtins.bool = ...,
commit_edit_settings: builtins.bool = ...,
add_contact: global___SharedContact | None = ...,
key_verification: global___KeyVerificationAdmin | None = ...,
factory_reset_device: builtins.int = ...,
reboot_ota_seconds: builtins.int = ...,
exit_simulator: builtins.bool = ...,
@@ -624,9 +691,9 @@ class AdminMessage(google.protobuf.message.Message):
factory_reset_config: builtins.int = ...,
nodedb_reset: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "session_passkey", b"session_passkey", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["get_channel_request", "get_channel_response", "get_owner_request", "get_owner_response", "get_config_request", "get_config_response", "get_module_config_request", "get_module_config_response", "get_canned_message_module_messages_request", "get_canned_message_module_messages_response", "get_device_metadata_request", "get_device_metadata_response", "get_ringtone_request", "get_ringtone_response", "get_device_connection_status_request", "get_device_connection_status_response", "set_ham_mode", "get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", "enter_dfu_mode_request", "delete_file_request", "set_scale", "backup_preferences", "restore_preferences", "remove_backup_preferences", "set_owner", "set_channel", "set_config", "set_module_config", "set_canned_message_module_messages", "set_ringtone_message", "remove_by_nodenum", "set_favorite_node", "remove_favorite_node", "set_fixed_position", "remove_fixed_position", "set_time_only", "get_ui_config_request", "get_ui_config_response", "store_ui_config", "set_ignored_node", "remove_ignored_node", "begin_edit_settings", "commit_edit_settings", "factory_reset_device", "reboot_ota_seconds", "exit_simulator", "reboot_seconds", "shutdown_seconds", "factory_reset_config", "nodedb_reset"] | None: ...
def HasField(self, field_name: typing.Literal["add_contact", b"add_contact", "backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "key_verification", b"key_verification", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "send_input_event", b"send_input_event", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["add_contact", b"add_contact", "backup_preferences", b"backup_preferences", "begin_edit_settings", b"begin_edit_settings", "commit_edit_settings", b"commit_edit_settings", "delete_file_request", b"delete_file_request", "enter_dfu_mode_request", b"enter_dfu_mode_request", "exit_simulator", b"exit_simulator", "factory_reset_config", b"factory_reset_config", "factory_reset_device", b"factory_reset_device", "get_canned_message_module_messages_request", b"get_canned_message_module_messages_request", "get_canned_message_module_messages_response", b"get_canned_message_module_messages_response", "get_channel_request", b"get_channel_request", "get_channel_response", b"get_channel_response", "get_config_request", b"get_config_request", "get_config_response", b"get_config_response", "get_device_connection_status_request", b"get_device_connection_status_request", "get_device_connection_status_response", b"get_device_connection_status_response", "get_device_metadata_request", b"get_device_metadata_request", "get_device_metadata_response", b"get_device_metadata_response", "get_module_config_request", b"get_module_config_request", "get_module_config_response", b"get_module_config_response", "get_node_remote_hardware_pins_request", b"get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", b"get_node_remote_hardware_pins_response", "get_owner_request", b"get_owner_request", "get_owner_response", b"get_owner_response", "get_ringtone_request", b"get_ringtone_request", "get_ringtone_response", b"get_ringtone_response", "get_ui_config_request", b"get_ui_config_request", "get_ui_config_response", b"get_ui_config_response", "key_verification", b"key_verification", "nodedb_reset", b"nodedb_reset", "payload_variant", b"payload_variant", "reboot_ota_seconds", b"reboot_ota_seconds", "reboot_seconds", b"reboot_seconds", "remove_backup_preferences", b"remove_backup_preferences", "remove_by_nodenum", b"remove_by_nodenum", "remove_favorite_node", b"remove_favorite_node", "remove_fixed_position", b"remove_fixed_position", "remove_ignored_node", b"remove_ignored_node", "restore_preferences", b"restore_preferences", "send_input_event", b"send_input_event", "session_passkey", b"session_passkey", "set_canned_message_module_messages", b"set_canned_message_module_messages", "set_channel", b"set_channel", "set_config", b"set_config", "set_favorite_node", b"set_favorite_node", "set_fixed_position", b"set_fixed_position", "set_ham_mode", b"set_ham_mode", "set_ignored_node", b"set_ignored_node", "set_module_config", b"set_module_config", "set_owner", b"set_owner", "set_ringtone_message", b"set_ringtone_message", "set_scale", b"set_scale", "set_time_only", b"set_time_only", "shutdown_seconds", b"shutdown_seconds", "store_ui_config", b"store_ui_config"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["get_channel_request", "get_channel_response", "get_owner_request", "get_owner_response", "get_config_request", "get_config_response", "get_module_config_request", "get_module_config_response", "get_canned_message_module_messages_request", "get_canned_message_module_messages_response", "get_device_metadata_request", "get_device_metadata_response", "get_ringtone_request", "get_ringtone_response", "get_device_connection_status_request", "get_device_connection_status_response", "set_ham_mode", "get_node_remote_hardware_pins_request", "get_node_remote_hardware_pins_response", "enter_dfu_mode_request", "delete_file_request", "set_scale", "backup_preferences", "restore_preferences", "remove_backup_preferences", "send_input_event", "set_owner", "set_channel", "set_config", "set_module_config", "set_canned_message_module_messages", "set_ringtone_message", "remove_by_nodenum", "set_favorite_node", "remove_favorite_node", "set_fixed_position", "remove_fixed_position", "set_time_only", "get_ui_config_request", "get_ui_config_response", "store_ui_config", "set_ignored_node", "remove_ignored_node", "begin_edit_settings", "commit_edit_settings", "add_contact", "key_verification", "factory_reset_device", "reboot_ota_seconds", "exit_simulator", "reboot_seconds", "shutdown_seconds", "factory_reset_config", "nodedb_reset"] | None: ...
global___AdminMessage = AdminMessage
@@ -695,3 +762,122 @@ class NodeRemoteHardwarePinsResponse(google.protobuf.message.Message):
def ClearField(self, field_name: typing.Literal["node_remote_hardware_pins", b"node_remote_hardware_pins"]) -> None: ...
global___NodeRemoteHardwarePinsResponse = NodeRemoteHardwarePinsResponse
@typing.final
class SharedContact(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NODE_NUM_FIELD_NUMBER: builtins.int
USER_FIELD_NUMBER: builtins.int
SHOULD_IGNORE_FIELD_NUMBER: builtins.int
node_num: builtins.int
"""
The node number of the contact
"""
should_ignore: builtins.bool
"""
Add this contact to the blocked / ignored list
"""
@property
def user(self) -> meshtastic.protobuf.mesh_pb2.User:
"""
The User of the contact
"""
def __init__(
self,
*,
node_num: builtins.int = ...,
user: meshtastic.protobuf.mesh_pb2.User | None = ...,
should_ignore: builtins.bool = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["user", b"user"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["node_num", b"node_num", "should_ignore", b"should_ignore", "user", b"user"]) -> None: ...
global___SharedContact = SharedContact
@typing.final
class KeyVerificationAdmin(google.protobuf.message.Message):
"""
This message is used by a client to initiate or complete a key verification
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _MessageType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _MessageTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[KeyVerificationAdmin._MessageType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
INITIATE_VERIFICATION: KeyVerificationAdmin._MessageType.ValueType # 0
"""
This is the first stage, where a client initiates
"""
PROVIDE_SECURITY_NUMBER: KeyVerificationAdmin._MessageType.ValueType # 1
"""
After the nonce has been returned over the mesh, the client prompts for the security number
And uses this message to provide it to the node.
"""
DO_VERIFY: KeyVerificationAdmin._MessageType.ValueType # 2
"""
Once the user has compared the verification message, this message notifies the node.
"""
DO_NOT_VERIFY: KeyVerificationAdmin._MessageType.ValueType # 3
"""
This is the cancel path, can be taken at any point
"""
class MessageType(_MessageType, metaclass=_MessageTypeEnumTypeWrapper):
"""
Three stages of this request.
"""
INITIATE_VERIFICATION: KeyVerificationAdmin.MessageType.ValueType # 0
"""
This is the first stage, where a client initiates
"""
PROVIDE_SECURITY_NUMBER: KeyVerificationAdmin.MessageType.ValueType # 1
"""
After the nonce has been returned over the mesh, the client prompts for the security number
And uses this message to provide it to the node.
"""
DO_VERIFY: KeyVerificationAdmin.MessageType.ValueType # 2
"""
Once the user has compared the verification message, this message notifies the node.
"""
DO_NOT_VERIFY: KeyVerificationAdmin.MessageType.ValueType # 3
"""
This is the cancel path, can be taken at any point
"""
MESSAGE_TYPE_FIELD_NUMBER: builtins.int
REMOTE_NODENUM_FIELD_NUMBER: builtins.int
NONCE_FIELD_NUMBER: builtins.int
SECURITY_NUMBER_FIELD_NUMBER: builtins.int
message_type: global___KeyVerificationAdmin.MessageType.ValueType
remote_nodenum: builtins.int
"""
The nodenum we're requesting
"""
nonce: builtins.int
"""
The nonce is used to track the connection
"""
security_number: builtins.int
"""
The 4 digit code generated by the remote node, and communicated outside the mesh
"""
def __init__(
self,
*,
message_type: global___KeyVerificationAdmin.MessageType.ValueType = ...,
remote_nodenum: builtins.int = ...,
nonce: builtins.int = ...,
security_number: builtins.int | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_security_number", b"_security_number", "security_number", b"security_number"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_security_number", b"_security_number", "message_type", b"message_type", "nonce", b"nonce", "remote_nodenum", b"remote_nodenum", "security_number", b"security_number"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_security_number", b"_security_number"]) -> typing.Literal["security_number"] | None: ...
global___KeyVerificationAdmin = KeyVerificationAdmin

View File

File diff suppressed because one or more lines are too long

View File

@@ -272,6 +272,73 @@ class Config(google.protobuf.message.Message):
Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing.
"""
class _BuzzerMode:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _BuzzerModeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Config.DeviceConfig._BuzzerMode.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
ALL_ENABLED: Config.DeviceConfig._BuzzerMode.ValueType # 0
"""
Default behavior.
Buzzer is enabled for all audio feedback including button presses and alerts.
"""
DISABLED: Config.DeviceConfig._BuzzerMode.ValueType # 1
"""
Disabled.
All buzzer audio feedback is disabled.
"""
NOTIFICATIONS_ONLY: Config.DeviceConfig._BuzzerMode.ValueType # 2
"""
Notifications Only.
Buzzer is enabled only for notifications and alerts, but not for button presses.
External notification config determines the specifics of the notification behavior.
"""
SYSTEM_ONLY: Config.DeviceConfig._BuzzerMode.ValueType # 3
"""
Non-notification system buzzer tones only.
Buzzer is enabled only for non-notification tones such as button presses, startup, shutdown, but not for alerts.
"""
DIRECT_MSG_ONLY: Config.DeviceConfig._BuzzerMode.ValueType # 4
"""
Direct Message notifications only.
Buzzer is enabled only for direct messages and alerts, but not for button presses.
External notification config determines the specifics of the notification behavior.
"""
class BuzzerMode(_BuzzerMode, metaclass=_BuzzerModeEnumTypeWrapper):
"""
Defines buzzer behavior for audio feedback
"""
ALL_ENABLED: Config.DeviceConfig.BuzzerMode.ValueType # 0
"""
Default behavior.
Buzzer is enabled for all audio feedback including button presses and alerts.
"""
DISABLED: Config.DeviceConfig.BuzzerMode.ValueType # 1
"""
Disabled.
All buzzer audio feedback is disabled.
"""
NOTIFICATIONS_ONLY: Config.DeviceConfig.BuzzerMode.ValueType # 2
"""
Notifications Only.
Buzzer is enabled only for notifications and alerts, but not for button presses.
External notification config determines the specifics of the notification behavior.
"""
SYSTEM_ONLY: Config.DeviceConfig.BuzzerMode.ValueType # 3
"""
Non-notification system buzzer tones only.
Buzzer is enabled only for non-notification tones such as button presses, startup, shutdown, but not for alerts.
"""
DIRECT_MSG_ONLY: Config.DeviceConfig.BuzzerMode.ValueType # 4
"""
Direct Message notifications only.
Buzzer is enabled only for direct messages and alerts, but not for button presses.
External notification config determines the specifics of the notification behavior.
"""
ROLE_FIELD_NUMBER: builtins.int
SERIAL_ENABLED_FIELD_NUMBER: builtins.int
BUTTON_GPIO_FIELD_NUMBER: builtins.int
@@ -283,6 +350,7 @@ class Config(google.protobuf.message.Message):
DISABLE_TRIPLE_CLICK_FIELD_NUMBER: builtins.int
TZDEF_FIELD_NUMBER: builtins.int
LED_HEARTBEAT_DISABLED_FIELD_NUMBER: builtins.int
BUZZER_MODE_FIELD_NUMBER: builtins.int
role: global___Config.DeviceConfig.Role.ValueType
"""
Sets the role of node
@@ -333,6 +401,11 @@ class Config(google.protobuf.message.Message):
"""
If true, disable the default blinking LED (LED_PIN) behavior on the device
"""
buzzer_mode: global___Config.DeviceConfig.BuzzerMode.ValueType
"""
Controls buzzer behavior for audio feedback
Defaults to ENABLED
"""
def __init__(
self,
*,
@@ -347,8 +420,9 @@ class Config(google.protobuf.message.Message):
disable_triple_click: builtins.bool = ...,
tzdef: builtins.str = ...,
led_heartbeat_disabled: builtins.bool = ...,
buzzer_mode: global___Config.DeviceConfig.BuzzerMode.ValueType = ...,
) -> 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: ...
def ClearField(self, field_name: typing.Literal["button_gpio", b"button_gpio", "buzzer_gpio", b"buzzer_gpio", "buzzer_mode", b"buzzer_mode", "disable_triple_click", b"disable_triple_click", "double_tap_as_button_press", b"double_tap_as_button_press", "is_managed", b"is_managed", "led_heartbeat_disabled", b"led_heartbeat_disabled", "node_info_broadcast_secs", b"node_info_broadcast_secs", "rebroadcast_mode", b"rebroadcast_mode", "role", b"role", "serial_enabled", b"serial_enabled", "tzdef", b"tzdef"]) -> None: ...
@typing.final
class PositionConfig(google.protobuf.message.Message):
@@ -615,7 +689,7 @@ class Config(google.protobuf.message.Message):
POWERMON_ENABLES_FIELD_NUMBER: builtins.int
is_power_saving: builtins.bool
"""
Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
Don't use this setting if you want to use your device with the phone apps or are using a device without a user button.
Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles
"""
@@ -781,6 +855,7 @@ class Config(google.protobuf.message.Message):
IPV4_CONFIG_FIELD_NUMBER: builtins.int
RSYSLOG_SERVER_FIELD_NUMBER: builtins.int
ENABLED_PROTOCOLS_FIELD_NUMBER: builtins.int
IPV6_ENABLED_FIELD_NUMBER: builtins.int
wifi_enabled: builtins.bool
"""
Enable WiFi (disables Bluetooth)
@@ -796,7 +871,7 @@ class Config(google.protobuf.message.Message):
"""
ntp_server: builtins.str
"""
NTP server to use if WiFi is conneced, defaults to `0.pool.ntp.org`
NTP server to use if WiFi is conneced, defaults to `meshtastic.pool.ntp.org`
"""
eth_enabled: builtins.bool
"""
@@ -814,6 +889,10 @@ class Config(google.protobuf.message.Message):
"""
Flags for enabling/disabling network protocols
"""
ipv6_enabled: builtins.bool
"""
Enable/Disable ipv6 support
"""
@property
def ipv4_config(self) -> global___Config.NetworkConfig.IpV4Config:
"""
@@ -832,9 +911,10 @@ class Config(google.protobuf.message.Message):
ipv4_config: global___Config.NetworkConfig.IpV4Config | None = ...,
rsyslog_server: builtins.str = ...,
enabled_protocols: builtins.int = ...,
ipv6_enabled: builtins.bool = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["ipv4_config", b"ipv4_config"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["address_mode", b"address_mode", "enabled_protocols", b"enabled_protocols", "eth_enabled", b"eth_enabled", "ipv4_config", b"ipv4_config", "ntp_server", b"ntp_server", "rsyslog_server", b"rsyslog_server", "wifi_enabled", b"wifi_enabled", "wifi_psk", b"wifi_psk", "wifi_ssid", b"wifi_ssid"]) -> None: ...
def ClearField(self, field_name: typing.Literal["address_mode", b"address_mode", "enabled_protocols", b"enabled_protocols", "eth_enabled", b"eth_enabled", "ipv4_config", b"ipv4_config", "ipv6_enabled", b"ipv6_enabled", "ntp_server", b"ntp_server", "rsyslog_server", b"rsyslog_server", "wifi_enabled", b"wifi_enabled", "wifi_psk", b"wifi_psk", "wifi_ssid", b"wifi_ssid"]) -> None: ...
@typing.final
class DisplayConfig(google.protobuf.message.Message):
@@ -956,18 +1036,22 @@ class Config(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
OLED_AUTO: Config.DisplayConfig._OledType.ValueType # 0
"""
Default / Auto
Default / Autodetect
"""
OLED_SSD1306: Config.DisplayConfig._OledType.ValueType # 1
"""
Default / Auto
Default / Autodetect
"""
OLED_SH1106: Config.DisplayConfig._OledType.ValueType # 2
"""
Default / Auto
Default / Autodetect
"""
OLED_SH1107: Config.DisplayConfig._OledType.ValueType # 3
"""
Can not be auto detected but set by proto. Used for 128x64 screens
"""
OLED_SH1107_128_128: Config.DisplayConfig._OledType.ValueType # 4
"""
Can not be auto detected but set by proto. Used for 128x128 screens
"""
@@ -978,18 +1062,22 @@ class Config(google.protobuf.message.Message):
OLED_AUTO: Config.DisplayConfig.OledType.ValueType # 0
"""
Default / Auto
Default / Autodetect
"""
OLED_SSD1306: Config.DisplayConfig.OledType.ValueType # 1
"""
Default / Auto
Default / Autodetect
"""
OLED_SH1106: Config.DisplayConfig.OledType.ValueType # 2
"""
Default / Auto
Default / Autodetect
"""
OLED_SH1107: Config.DisplayConfig.OledType.ValueType # 3
"""
Can not be auto detected but set by proto. Used for 128x64 screens
"""
OLED_SH1107_128_128: Config.DisplayConfig.OledType.ValueType # 4
"""
Can not be auto detected but set by proto. Used for 128x128 screens
"""
@@ -1126,6 +1214,7 @@ class Config(google.protobuf.message.Message):
"""
gps_format: global___Config.DisplayConfig.GpsCoordinateFormat.ValueType
"""
Deprecated in 2.7.4: Unused
How the GPS coordinates are formatted on the OLED screen.
"""
auto_screen_carousel_secs: builtins.int
@@ -1291,6 +1380,26 @@ class Config(google.protobuf.message.Message):
"""
Philippines 915mhz
"""
ANZ_433: Config.LoRaConfig._RegionCode.ValueType # 22
"""
Australia / New Zealand 433MHz
"""
KZ_433: Config.LoRaConfig._RegionCode.ValueType # 23
"""
Kazakhstan 433MHz
"""
KZ_863: Config.LoRaConfig._RegionCode.ValueType # 24
"""
Kazakhstan 863MHz
"""
NP_865: Config.LoRaConfig._RegionCode.ValueType # 25
"""
Nepal 865MHz
"""
BR_902: Config.LoRaConfig._RegionCode.ValueType # 26
"""
Brazil 902MHz
"""
class RegionCode(_RegionCode, metaclass=_RegionCodeEnumTypeWrapper): ...
UNSET: Config.LoRaConfig.RegionCode.ValueType # 0
@@ -1381,6 +1490,26 @@ class Config(google.protobuf.message.Message):
"""
Philippines 915mhz
"""
ANZ_433: Config.LoRaConfig.RegionCode.ValueType # 22
"""
Australia / New Zealand 433MHz
"""
KZ_433: Config.LoRaConfig.RegionCode.ValueType # 23
"""
Kazakhstan 433MHz
"""
KZ_863: Config.LoRaConfig.RegionCode.ValueType # 24
"""
Kazakhstan 863MHz
"""
NP_865: Config.LoRaConfig.RegionCode.ValueType # 25
"""
Nepal 865MHz
"""
BR_902: Config.LoRaConfig.RegionCode.ValueType # 26
"""
Brazil 902MHz
"""
class _ModemPreset:
ValueType = typing.NewType("ValueType", builtins.int)

View File

@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/device_ui.proto\x12\x13meshtastic.protobuf\"\xeb\x03\n\x0e\x44\x65viceUIConfig\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x19\n\x11screen_brightness\x18\x02 \x01(\r\x12\x16\n\x0escreen_timeout\x18\x03 \x01(\r\x12\x13\n\x0bscreen_lock\x18\x04 \x01(\x08\x12\x15\n\rsettings_lock\x18\x05 \x01(\x08\x12\x10\n\x08pin_code\x18\x06 \x01(\r\x12)\n\x05theme\x18\x07 \x01(\x0e\x32\x1a.meshtastic.protobuf.Theme\x12\x15\n\ralert_enabled\x18\x08 \x01(\x08\x12\x16\n\x0e\x62\x61nner_enabled\x18\t \x01(\x08\x12\x14\n\x0cring_tone_id\x18\n \x01(\r\x12/\n\x08language\x18\x0b \x01(\x0e\x32\x1d.meshtastic.protobuf.Language\x12\x34\n\x0bnode_filter\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.NodeFilter\x12:\n\x0enode_highlight\x18\r \x01(\x0b\x32\".meshtastic.protobuf.NodeHighlight\x12\x18\n\x10\x63\x61libration_data\x18\x0e \x01(\x0c\x12*\n\x08map_data\x18\x0f \x01(\x0b\x32\x18.meshtastic.protobuf.Map\"\xa7\x01\n\nNodeFilter\x12\x16\n\x0eunknown_switch\x18\x01 \x01(\x08\x12\x16\n\x0eoffline_switch\x18\x02 \x01(\x08\x12\x19\n\x11public_key_switch\x18\x03 \x01(\x08\x12\x11\n\thops_away\x18\x04 \x01(\x05\x12\x17\n\x0fposition_switch\x18\x05 \x01(\x08\x12\x11\n\tnode_name\x18\x06 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\x05\"~\n\rNodeHighlight\x12\x13\n\x0b\x63hat_switch\x18\x01 \x01(\x08\x12\x17\n\x0fposition_switch\x18\x02 \x01(\x08\x12\x18\n\x10telemetry_switch\x18\x03 \x01(\x08\x12\x12\n\niaq_switch\x18\x04 \x01(\x08\x12\x11\n\tnode_name\x18\x05 \x01(\t\"=\n\x08GeoPoint\x12\x0c\n\x04zoom\x18\x01 \x01(\x05\x12\x10\n\x08latitude\x18\x02 \x01(\x05\x12\x11\n\tlongitude\x18\x03 \x01(\x05\"U\n\x03Map\x12+\n\x04home\x18\x01 \x01(\x0b\x32\x1d.meshtastic.protobuf.GeoPoint\x12\r\n\x05style\x18\x02 \x01(\t\x12\x12\n\nfollow_gps\x18\x03 \x01(\x08*%\n\x05Theme\x12\x08\n\x04\x44\x41RK\x10\x00\x12\t\n\x05LIGHT\x10\x01\x12\x07\n\x03RED\x10\x02*\x8b\x02\n\x08Language\x12\x0b\n\x07\x45NGLISH\x10\x00\x12\n\n\x06\x46RENCH\x10\x01\x12\n\n\x06GERMAN\x10\x02\x12\x0b\n\x07ITALIAN\x10\x03\x12\x0e\n\nPORTUGUESE\x10\x04\x12\x0b\n\x07SPANISH\x10\x05\x12\x0b\n\x07SWEDISH\x10\x06\x12\x0b\n\x07\x46INNISH\x10\x07\x12\n\n\x06POLISH\x10\x08\x12\x0b\n\x07TURKISH\x10\t\x12\x0b\n\x07SERBIAN\x10\n\x12\x0b\n\x07RUSSIAN\x10\x0b\x12\t\n\x05\x44UTCH\x10\x0c\x12\t\n\x05GREEK\x10\r\x12\r\n\tNORWEGIAN\x10\x0e\x12\r\n\tSLOVENIAN\x10\x0f\x12\x16\n\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n\x13TRADITIONAL_CHINESE\x10\x1f\x42\x63\n\x13\x63om.geeksville.meshB\x0e\x44\x65viceUIProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/device_ui.proto\x12\x13meshtastic.protobuf\"\xda\x04\n\x0e\x44\x65viceUIConfig\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x19\n\x11screen_brightness\x18\x02 \x01(\r\x12\x16\n\x0escreen_timeout\x18\x03 \x01(\r\x12\x13\n\x0bscreen_lock\x18\x04 \x01(\x08\x12\x15\n\rsettings_lock\x18\x05 \x01(\x08\x12\x10\n\x08pin_code\x18\x06 \x01(\r\x12)\n\x05theme\x18\x07 \x01(\x0e\x32\x1a.meshtastic.protobuf.Theme\x12\x15\n\ralert_enabled\x18\x08 \x01(\x08\x12\x16\n\x0e\x62\x61nner_enabled\x18\t \x01(\x08\x12\x14\n\x0cring_tone_id\x18\n \x01(\r\x12/\n\x08language\x18\x0b \x01(\x0e\x32\x1d.meshtastic.protobuf.Language\x12\x34\n\x0bnode_filter\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.NodeFilter\x12:\n\x0enode_highlight\x18\r \x01(\x0b\x32\".meshtastic.protobuf.NodeHighlight\x12\x18\n\x10\x63\x61libration_data\x18\x0e \x01(\x0c\x12*\n\x08map_data\x18\x0f \x01(\x0b\x32\x18.meshtastic.protobuf.Map\x12\x36\n\x0c\x63ompass_mode\x18\x10 \x01(\x0e\x32 .meshtastic.protobuf.CompassMode\x12\x18\n\x10screen_rgb_color\x18\x11 \x01(\r\x12\x1b\n\x13is_clockface_analog\x18\x12 \x01(\x08\"\xa7\x01\n\nNodeFilter\x12\x16\n\x0eunknown_switch\x18\x01 \x01(\x08\x12\x16\n\x0eoffline_switch\x18\x02 \x01(\x08\x12\x19\n\x11public_key_switch\x18\x03 \x01(\x08\x12\x11\n\thops_away\x18\x04 \x01(\x05\x12\x17\n\x0fposition_switch\x18\x05 \x01(\x08\x12\x11\n\tnode_name\x18\x06 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\x05\"~\n\rNodeHighlight\x12\x13\n\x0b\x63hat_switch\x18\x01 \x01(\x08\x12\x17\n\x0fposition_switch\x18\x02 \x01(\x08\x12\x18\n\x10telemetry_switch\x18\x03 \x01(\x08\x12\x12\n\niaq_switch\x18\x04 \x01(\x08\x12\x11\n\tnode_name\x18\x05 \x01(\t\"=\n\x08GeoPoint\x12\x0c\n\x04zoom\x18\x01 \x01(\x05\x12\x10\n\x08latitude\x18\x02 \x01(\x05\x12\x11\n\tlongitude\x18\x03 \x01(\x05\"U\n\x03Map\x12+\n\x04home\x18\x01 \x01(\x0b\x32\x1d.meshtastic.protobuf.GeoPoint\x12\r\n\x05style\x18\x02 \x01(\t\x12\x12\n\nfollow_gps\x18\x03 \x01(\x08*>\n\x0b\x43ompassMode\x12\x0b\n\x07\x44YNAMIC\x10\x00\x12\x0e\n\nFIXED_RING\x10\x01\x12\x12\n\x0e\x46REEZE_HEADING\x10\x02*%\n\x05Theme\x12\x08\n\x04\x44\x41RK\x10\x00\x12\t\n\x05LIGHT\x10\x01\x12\x07\n\x03RED\x10\x02*\xa9\x02\n\x08Language\x12\x0b\n\x07\x45NGLISH\x10\x00\x12\n\n\x06\x46RENCH\x10\x01\x12\n\n\x06GERMAN\x10\x02\x12\x0b\n\x07ITALIAN\x10\x03\x12\x0e\n\nPORTUGUESE\x10\x04\x12\x0b\n\x07SPANISH\x10\x05\x12\x0b\n\x07SWEDISH\x10\x06\x12\x0b\n\x07\x46INNISH\x10\x07\x12\n\n\x06POLISH\x10\x08\x12\x0b\n\x07TURKISH\x10\t\x12\x0b\n\x07SERBIAN\x10\n\x12\x0b\n\x07RUSSIAN\x10\x0b\x12\t\n\x05\x44UTCH\x10\x0c\x12\t\n\x05GREEK\x10\r\x12\r\n\tNORWEGIAN\x10\x0e\x12\r\n\tSLOVENIAN\x10\x0f\x12\r\n\tUKRAINIAN\x10\x10\x12\r\n\tBULGARIAN\x10\x11\x12\x16\n\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n\x13TRADITIONAL_CHINESE\x10\x1f\x42\x63\n\x13\x63om.geeksville.meshB\x0e\x44\x65viceUIProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,18 +21,20 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.device_
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\016DeviceUIProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_THEME']._serialized_start=1002
_globals['_THEME']._serialized_end=1039
_globals['_LANGUAGE']._serialized_start=1042
_globals['_LANGUAGE']._serialized_end=1309
_globals['_COMPASSMODE']._serialized_start=1113
_globals['_COMPASSMODE']._serialized_end=1175
_globals['_THEME']._serialized_start=1177
_globals['_THEME']._serialized_end=1214
_globals['_LANGUAGE']._serialized_start=1217
_globals['_LANGUAGE']._serialized_end=1514
_globals['_DEVICEUICONFIG']._serialized_start=61
_globals['_DEVICEUICONFIG']._serialized_end=552
_globals['_NODEFILTER']._serialized_start=555
_globals['_NODEFILTER']._serialized_end=722
_globals['_NODEHIGHLIGHT']._serialized_start=724
_globals['_NODEHIGHLIGHT']._serialized_end=850
_globals['_GEOPOINT']._serialized_start=852
_globals['_GEOPOINT']._serialized_end=913
_globals['_MAP']._serialized_start=915
_globals['_MAP']._serialized_end=1000
_globals['_DEVICEUICONFIG']._serialized_end=663
_globals['_NODEFILTER']._serialized_start=666
_globals['_NODEFILTER']._serialized_end=833
_globals['_NODEHIGHLIGHT']._serialized_start=835
_globals['_NODEHIGHLIGHT']._serialized_end=961
_globals['_GEOPOINT']._serialized_start=963
_globals['_GEOPOINT']._serialized_end=1024
_globals['_MAP']._serialized_start=1026
_globals['_MAP']._serialized_end=1111
# @@protoc_insertion_point(module_scope)

View File

@@ -17,6 +17,41 @@ else:
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _CompassMode:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _CompassModeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_CompassMode.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DYNAMIC: _CompassMode.ValueType # 0
"""
Compass with dynamic ring and heading
"""
FIXED_RING: _CompassMode.ValueType # 1
"""
Compass with fixed ring and heading
"""
FREEZE_HEADING: _CompassMode.ValueType # 2
"""
Compass with heading and freeze option
"""
class CompassMode(_CompassMode, metaclass=_CompassModeEnumTypeWrapper): ...
DYNAMIC: CompassMode.ValueType # 0
"""
Compass with dynamic ring and heading
"""
FIXED_RING: CompassMode.ValueType # 1
"""
Compass with fixed ring and heading
"""
FREEZE_HEADING: CompassMode.ValueType # 2
"""
Compass with heading and freeze option
"""
global___CompassMode = CompassMode
class _Theme:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
@@ -122,6 +157,14 @@ class _LanguageEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumT
"""
Slovenian
"""
UKRAINIAN: _Language.ValueType # 16
"""
Ukrainian
"""
BULGARIAN: _Language.ValueType # 17
"""
Bulgarian
"""
SIMPLIFIED_CHINESE: _Language.ValueType # 30
"""
Simplified Chinese (experimental)
@@ -200,6 +243,14 @@ SLOVENIAN: Language.ValueType # 15
"""
Slovenian
"""
UKRAINIAN: Language.ValueType # 16
"""
Ukrainian
"""
BULGARIAN: Language.ValueType # 17
"""
Bulgarian
"""
SIMPLIFIED_CHINESE: Language.ValueType # 30
"""
Simplified Chinese (experimental)
@@ -233,6 +284,9 @@ class DeviceUIConfig(google.protobuf.message.Message):
NODE_HIGHLIGHT_FIELD_NUMBER: builtins.int
CALIBRATION_DATA_FIELD_NUMBER: builtins.int
MAP_DATA_FIELD_NUMBER: builtins.int
COMPASS_MODE_FIELD_NUMBER: builtins.int
SCREEN_RGB_COLOR_FIELD_NUMBER: builtins.int
IS_CLOCKFACE_ANALOG_FIELD_NUMBER: builtins.int
version: builtins.int
"""
A version integer used to invalidate saved files when we make incompatible changes.
@@ -269,6 +323,20 @@ class DeviceUIConfig(google.protobuf.message.Message):
"""
8 integers for screen calibration data
"""
compass_mode: global___CompassMode.ValueType
"""
Compass mode
"""
screen_rgb_color: builtins.int
"""
RGB color for BaseUI
0xRRGGBB format, e.g. 0xFF0000 for red
"""
is_clockface_analog: builtins.bool
"""
Clockface analog style
true for analog clockface, false for digital clockface
"""
@property
def node_filter(self) -> global___NodeFilter:
"""
@@ -305,9 +373,12 @@ class DeviceUIConfig(google.protobuf.message.Message):
node_highlight: global___NodeHighlight | None = ...,
calibration_data: builtins.bytes = ...,
map_data: global___Map | None = ...,
compass_mode: global___CompassMode.ValueType = ...,
screen_rgb_color: builtins.int = ...,
is_clockface_analog: builtins.bool = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["alert_enabled", b"alert_enabled", "banner_enabled", b"banner_enabled", "calibration_data", b"calibration_data", "language", b"language", "map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight", "pin_code", b"pin_code", "ring_tone_id", b"ring_tone_id", "screen_brightness", b"screen_brightness", "screen_lock", b"screen_lock", "screen_timeout", b"screen_timeout", "settings_lock", b"settings_lock", "theme", b"theme", "version", b"version"]) -> None: ...
def ClearField(self, field_name: typing.Literal["alert_enabled", b"alert_enabled", "banner_enabled", b"banner_enabled", "calibration_data", b"calibration_data", "compass_mode", b"compass_mode", "is_clockface_analog", b"is_clockface_analog", "language", b"language", "map_data", b"map_data", "node_filter", b"node_filter", "node_highlight", b"node_highlight", "pin_code", b"pin_code", "ring_tone_id", b"ring_tone_id", "screen_brightness", b"screen_brightness", "screen_lock", b"screen_lock", "screen_rgb_color", b"screen_rgb_color", "screen_timeout", b"screen_timeout", "settings_lock", b"settings_lock", "theme", b"theme", "version", b"version"]) -> None: ...
global___DeviceUIConfig = DeviceUIConfig

View File

@@ -12,14 +12,14 @@ _sym_db = _symbol_database.Default()
from meshtastic.protobuf import channel_pb2 as meshtastic_dot_protobuf_dot_channel__pb2
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
from meshtastic.protobuf import telemetry_pb2 as meshtastic_dot_protobuf_dot_telemetry__pb2
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
import nanopb_pb2 as nanopb__pb2
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 nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/deviceonly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/config.proto\x1a#meshtastic/protobuf/localonly.proto\x1a\x0cnanopb.proto\"\x99\x01\n\x0cPositionLite\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x0c\n\x04time\x18\x04 \x01(\x07\x12@\n\x0flocation_source\x18\x05 \x01(\x0e\x32\'.meshtastic.protobuf.Position.LocSource\"\xe2\x01\n\x08UserLite\x12\x13\n\x07macaddr\x18\x01 \x01(\x0c\x42\x02\x18\x01\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x34\n\x08hw_model\x18\x04 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x13\n\x0bis_licensed\x18\x05 \x01(\x08\x12;\n\x04role\x18\x06 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x12\n\npublic_key\x18\x07 \x01(\x0c\"\xde\x02\n\x0cNodeInfoLite\x12\x0b\n\x03num\x18\x01 \x01(\r\x12+\n\x04user\x18\x02 \x01(\x0b\x32\x1d.meshtastic.protobuf.UserLite\x12\x33\n\x08position\x18\x03 \x01(\x0b\x32!.meshtastic.protobuf.PositionLite\x12\x0b\n\x03snr\x18\x04 \x01(\x02\x12\x12\n\nlast_heard\x18\x05 \x01(\x07\x12:\n\x0e\x64\x65vice_metrics\x18\x06 \x01(\x0b\x32\".meshtastic.protobuf.DeviceMetrics\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\r\x12\x10\n\x08via_mqtt\x18\x08 \x01(\x08\x12\x16\n\thops_away\x18\t \x01(\rH\x00\x88\x01\x01\x12\x13\n\x0bis_favorite\x18\n \x01(\x08\x12\x12\n\nis_ignored\x18\x0b \x01(\x08\x12\x10\n\x08next_hop\x18\x0c \x01(\rB\x0c\n\n_hops_away\"\xa1\x03\n\x0b\x44\x65viceState\x12\x30\n\x07my_node\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.MyNodeInfo\x12(\n\x05owner\x18\x03 \x01(\x0b\x32\x19.meshtastic.protobuf.User\x12\x36\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12\x38\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x13\n\x07no_save\x18\t \x01(\x08\x42\x02\x18\x01\x12\x19\n\rdid_gps_reset\x18\x0b \x01(\x08\x42\x02\x18\x01\x12\x34\n\x0brx_waypoint\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12M\n\x19node_remote_hardware_pins\x18\r \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePin\"}\n\x0cNodeDatabase\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\\\n\x05nodes\x18\x02 \x03(\x0b\x32!.meshtastic.protobuf.NodeInfoLiteB*\x92?\'\x92\x01$std::vector<meshtastic_NodeInfoLite>\"N\n\x0b\x43hannelFile\x12.\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1c.meshtastic.protobuf.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x86\x02\n\x11\x42\x61\x63kupPreferences\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\x07\x12\x30\n\x06\x63onfig\x18\x03 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfig\x12=\n\rmodule_config\x18\x04 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfig\x12\x32\n\x08\x63hannels\x18\x05 \x01(\x0b\x32 .meshtastic.protobuf.ChannelFile\x12(\n\x05owner\x18\x06 \x01(\x0b\x32\x19.meshtastic.protobuf.UserBm\n\x13\x63om.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x92?\x0b\xc2\x01\x08<vector>b\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/deviceonly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a#meshtastic/protobuf/telemetry.proto\x1a meshtastic/protobuf/nanopb.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\"\x94\x02\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\x12\x1c\n\x0fis_unmessagable\x18\t \x01(\x08H\x00\x88\x01\x01\x42\x12\n\x10_is_unmessagable\"\xf0\x02\n\x0cNodeInfoLite\x12\x0b\n\x03num\x18\x01 \x01(\r\x12+\n\x04user\x18\x02 \x01(\x0b\x32\x1d.meshtastic.protobuf.UserLite\x12\x33\n\x08position\x18\x03 \x01(\x0b\x32!.meshtastic.protobuf.PositionLite\x12\x0b\n\x03snr\x18\x04 \x01(\x02\x12\x12\n\nlast_heard\x18\x05 \x01(\x07\x12:\n\x0e\x64\x65vice_metrics\x18\x06 \x01(\x0b\x32\".meshtastic.protobuf.DeviceMetrics\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\r\x12\x10\n\x08via_mqtt\x18\x08 \x01(\x08\x12\x16\n\thops_away\x18\t \x01(\rH\x00\x88\x01\x01\x12\x13\n\x0bis_favorite\x18\n \x01(\x08\x12\x12\n\nis_ignored\x18\x0b \x01(\x08\x12\x10\n\x08next_hop\x18\x0c \x01(\r\x12\x10\n\x08\x62itfield\x18\r \x01(\rB\x0c\n\n_hops_away\"\xa1\x03\n\x0b\x44\x65viceState\x12\x30\n\x07my_node\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.MyNodeInfo\x12(\n\x05owner\x18\x03 \x01(\x0b\x32\x19.meshtastic.protobuf.User\x12\x36\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12\x38\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x13\n\x07no_save\x18\t \x01(\x08\x42\x02\x18\x01\x12\x19\n\rdid_gps_reset\x18\x0b \x01(\x08\x42\x02\x18\x01\x12\x34\n\x0brx_waypoint\x18\x0c \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12M\n\x19node_remote_hardware_pins\x18\r \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePin\"}\n\x0cNodeDatabase\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\\\n\x05nodes\x18\x02 \x03(\x0b\x32!.meshtastic.protobuf.NodeInfoLiteB*\x92?\'\x92\x01$std::vector<meshtastic_NodeInfoLite>\"N\n\x0b\x43hannelFile\x12.\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1c.meshtastic.protobuf.Channel\x12\x0f\n\x07version\x18\x02 \x01(\r\"\x86\x02\n\x11\x42\x61\x63kupPreferences\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x11\n\ttimestamp\x18\x02 \x01(\x07\x12\x30\n\x06\x63onfig\x18\x03 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfig\x12=\n\rmodule_config\x18\x04 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfig\x12\x32\n\x08\x63hannels\x18\x05 \x01(\x0b\x32 .meshtastic.protobuf.ChannelFile\x12(\n\x05owner\x18\x06 \x01(\x0b\x32\x19.meshtastic.protobuf.UserBm\n\x13\x63om.geeksville.meshB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x92?\x0b\xc2\x01\x08<vector>b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -35,18 +35,18 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_DEVICESTATE.fields_by_name['did_gps_reset']._serialized_options = b'\030\001'
_NODEDATABASE.fields_by_name['nodes']._options = None
_NODEDATABASE.fields_by_name['nodes']._serialized_options = b'\222?\'\222\001$std::vector<meshtastic_NodeInfoLite>'
_globals['_POSITIONLITE']._serialized_start=251
_globals['_POSITIONLITE']._serialized_end=404
_globals['_USERLITE']._serialized_start=407
_globals['_USERLITE']._serialized_end=633
_globals['_NODEINFOLITE']._serialized_start=636
_globals['_NODEINFOLITE']._serialized_end=986
_globals['_DEVICESTATE']._serialized_start=989
_globals['_DEVICESTATE']._serialized_end=1406
_globals['_NODEDATABASE']._serialized_start=1408
_globals['_NODEDATABASE']._serialized_end=1533
_globals['_CHANNELFILE']._serialized_start=1535
_globals['_CHANNELFILE']._serialized_end=1613
_globals['_BACKUPPREFERENCES']._serialized_start=1616
_globals['_BACKUPPREFERENCES']._serialized_end=1878
_globals['_POSITIONLITE']._serialized_start=271
_globals['_POSITIONLITE']._serialized_end=424
_globals['_USERLITE']._serialized_start=427
_globals['_USERLITE']._serialized_end=703
_globals['_NODEINFOLITE']._serialized_start=706
_globals['_NODEINFOLITE']._serialized_end=1074
_globals['_DEVICESTATE']._serialized_start=1077
_globals['_DEVICESTATE']._serialized_end=1494
_globals['_NODEDATABASE']._serialized_start=1496
_globals['_NODEDATABASE']._serialized_end=1621
_globals['_CHANNELFILE']._serialized_start=1623
_globals['_CHANNELFILE']._serialized_end=1701
_globals['_BACKUPPREFERENCES']._serialized_start=1704
_globals['_BACKUPPREFERENCES']._serialized_end=1966
# @@protoc_insertion_point(module_scope)

View File

@@ -79,6 +79,7 @@ class UserLite(google.protobuf.message.Message):
IS_LICENSED_FIELD_NUMBER: builtins.int
ROLE_FIELD_NUMBER: builtins.int
PUBLIC_KEY_FIELD_NUMBER: builtins.int
IS_UNMESSAGABLE_FIELD_NUMBER: builtins.int
macaddr: builtins.bytes
"""
This is the addr of the radio.
@@ -114,6 +115,10 @@ class UserLite(google.protobuf.message.Message):
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.
"""
is_unmessagable: builtins.bool
"""
Whether or not the node can be messaged
"""
def __init__(
self,
*,
@@ -124,8 +129,11 @@ class UserLite(google.protobuf.message.Message):
is_licensed: builtins.bool = ...,
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
public_key: builtins.bytes = ...,
is_unmessagable: builtins.bool | None = ...,
) -> 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: ...
def HasField(self, field_name: typing.Literal["_is_unmessagable", b"_is_unmessagable", "is_unmessagable", b"is_unmessagable"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_is_unmessagable", b"_is_unmessagable", "hw_model", b"hw_model", "is_licensed", b"is_licensed", "is_unmessagable", b"is_unmessagable", "long_name", b"long_name", "macaddr", b"macaddr", "public_key", b"public_key", "role", b"role", "short_name", b"short_name"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_is_unmessagable", b"_is_unmessagable"]) -> typing.Literal["is_unmessagable"] | None: ...
global___UserLite = UserLite
@@ -145,6 +153,7 @@ class NodeInfoLite(google.protobuf.message.Message):
IS_FAVORITE_FIELD_NUMBER: builtins.int
IS_IGNORED_FIELD_NUMBER: builtins.int
NEXT_HOP_FIELD_NUMBER: builtins.int
BITFIELD_FIELD_NUMBER: builtins.int
num: builtins.int
"""
The node number
@@ -184,6 +193,11 @@ class NodeInfoLite(google.protobuf.message.Message):
"""
Last byte of the node number of the node that should be used as the next hop to reach this node.
"""
bitfield: builtins.int
"""
Bitfield for storing booleans.
LSB 0 is_key_manually_verified
"""
@property
def user(self) -> global___UserLite:
"""
@@ -218,9 +232,10 @@ class NodeInfoLite(google.protobuf.message.Message):
is_favorite: builtins.bool = ...,
is_ignored: builtins.bool = ...,
next_hop: builtins.int = ...,
bitfield: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "position", b"position", "user", b"user"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "last_heard", b"last_heard", "next_hop", b"next_hop", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "bitfield", b"bitfield", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "last_heard", b"last_heard", "next_hop", b"next_hop", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_hops_away", b"_hops_away"]) -> typing.Literal["hops_away"] | None: ...
global___NodeInfoLite = NodeInfoLite

30
meshtastic/protobuf/interdevice_pb2.py generated Normal file
View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/interdevice.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%meshtastic/protobuf/interdevice.proto\x12\x13meshtastic.protobuf\"s\n\nSensorData\x12.\n\x04type\x18\x01 \x01(\x0e\x32 .meshtastic.protobuf.MessageType\x12\x15\n\x0b\x66loat_value\x18\x02 \x01(\x02H\x00\x12\x16\n\x0cuint32_value\x18\x03 \x01(\rH\x00\x42\x06\n\x04\x64\x61ta\"_\n\x12InterdeviceMessage\x12\x0e\n\x04nmea\x18\x01 \x01(\tH\x00\x12\x31\n\x06sensor\x18\x02 \x01(\x0b\x32\x1f.meshtastic.protobuf.SensorDataH\x00\x42\x06\n\x04\x64\x61ta*\xd5\x01\n\x0bMessageType\x12\x07\n\x03\x41\x43K\x10\x00\x12\x15\n\x10\x43OLLECT_INTERVAL\x10\xa0\x01\x12\x0c\n\x07\x42\x45\x45P_ON\x10\xa1\x01\x12\r\n\x08\x42\x45\x45P_OFF\x10\xa2\x01\x12\r\n\x08SHUTDOWN\x10\xa3\x01\x12\r\n\x08POWER_ON\x10\xa4\x01\x12\x0f\n\nSCD41_TEMP\x10\xb0\x01\x12\x13\n\x0eSCD41_HUMIDITY\x10\xb1\x01\x12\x0e\n\tSCD41_CO2\x10\xb2\x01\x12\x0f\n\nAHT20_TEMP\x10\xb3\x01\x12\x13\n\x0e\x41HT20_HUMIDITY\x10\xb4\x01\x12\x0f\n\nTVOC_INDEX\x10\xb5\x01\x42\x66\n\x13\x63om.geeksville.meshB\x11InterdeviceProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.interdevice_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\021InterdeviceProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_MESSAGETYPE']._serialized_start=277
_globals['_MESSAGETYPE']._serialized_end=490
_globals['_SENSORDATA']._serialized_start=62
_globals['_SENSORDATA']._serialized_end=177
_globals['_INTERDEVICEMESSAGE']._serialized_start=179
_globals['_INTERDEVICEMESSAGE']._serialized_end=274
# @@protoc_insertion_point(module_scope)

105
meshtastic/protobuf/interdevice_pb2.pyi generated Normal file
View File

@@ -0,0 +1,105 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import google.protobuf.descriptor
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _MessageType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _MessageTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_MessageType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
ACK: _MessageType.ValueType # 0
COLLECT_INTERVAL: _MessageType.ValueType # 160
"""in ms"""
BEEP_ON: _MessageType.ValueType # 161
"""duration ms"""
BEEP_OFF: _MessageType.ValueType # 162
"""cancel prematurely"""
SHUTDOWN: _MessageType.ValueType # 163
POWER_ON: _MessageType.ValueType # 164
SCD41_TEMP: _MessageType.ValueType # 176
SCD41_HUMIDITY: _MessageType.ValueType # 177
SCD41_CO2: _MessageType.ValueType # 178
AHT20_TEMP: _MessageType.ValueType # 179
AHT20_HUMIDITY: _MessageType.ValueType # 180
TVOC_INDEX: _MessageType.ValueType # 181
class MessageType(_MessageType, metaclass=_MessageTypeEnumTypeWrapper):
"""encapsulate up to 1k of NMEA string data"""
ACK: MessageType.ValueType # 0
COLLECT_INTERVAL: MessageType.ValueType # 160
"""in ms"""
BEEP_ON: MessageType.ValueType # 161
"""duration ms"""
BEEP_OFF: MessageType.ValueType # 162
"""cancel prematurely"""
SHUTDOWN: MessageType.ValueType # 163
POWER_ON: MessageType.ValueType # 164
SCD41_TEMP: MessageType.ValueType # 176
SCD41_HUMIDITY: MessageType.ValueType # 177
SCD41_CO2: MessageType.ValueType # 178
AHT20_TEMP: MessageType.ValueType # 179
AHT20_HUMIDITY: MessageType.ValueType # 180
TVOC_INDEX: MessageType.ValueType # 181
global___MessageType = MessageType
@typing.final
class SensorData(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
TYPE_FIELD_NUMBER: builtins.int
FLOAT_VALUE_FIELD_NUMBER: builtins.int
UINT32_VALUE_FIELD_NUMBER: builtins.int
type: global___MessageType.ValueType
"""The message type"""
float_value: builtins.float
uint32_value: builtins.int
def __init__(
self,
*,
type: global___MessageType.ValueType = ...,
float_value: builtins.float = ...,
uint32_value: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["data", b"data", "float_value", b"float_value", "uint32_value", b"uint32_value"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["data", b"data", "float_value", b"float_value", "type", b"type", "uint32_value", b"uint32_value"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["data", b"data"]) -> typing.Literal["float_value", "uint32_value"] | None: ...
global___SensorData = SensorData
@typing.final
class InterdeviceMessage(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NMEA_FIELD_NUMBER: builtins.int
SENSOR_FIELD_NUMBER: builtins.int
nmea: builtins.str
@property
def sensor(self) -> global___SensorData: ...
def __init__(
self,
*,
nmea: builtins.str = ...,
sensor: global___SensorData | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["data", b"data", "nmea", b"nmea", "sensor", b"sensor"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["data", b"data", "nmea", b"nmea", "sensor", b"sensor"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["data", b"data"]) -> typing.Literal["nmea", "sensor"] | None: ...
global___InterdeviceMessage = InterdeviceMessage

View File

File diff suppressed because one or more lines are too long

View File

@@ -295,7 +295,7 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
"""
TWC_MESH_V4: _HardwareModel.ValueType # 62
"""
TWC_MESH_V4
TWC_MESH_V4
Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS
"""
NRF52_PROMICRO_DIY: _HardwareModel.ValueType # 63
@@ -402,6 +402,94 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog
https://www.loraitalia.it
"""
XIAO_NRF52_KIT: _HardwareModel.ValueType # 88
"""
Seeed XIAO nRF52840 + Wio SX1262 kit
"""
THINKNODE_M1: _HardwareModel.ValueType # 89
"""
Elecrow ThinkNode M1 & M2
https://www.elecrow.com/wiki/ThinkNode-M1_Transceiver_Device(Meshtastic)_Power_By_nRF52840.html
https://www.elecrow.com/wiki/ThinkNode-M2_Transceiver_Device(Meshtastic)_Power_By_NRF52840.html (this actually uses ESP32-S3)
"""
THINKNODE_M2: _HardwareModel.ValueType # 90
T_ETH_ELITE: _HardwareModel.ValueType # 91
"""
Lilygo T-ETH-Elite
"""
HELTEC_SENSOR_HUB: _HardwareModel.ValueType # 92
"""
Heltec HRI-3621 industrial probe
"""
RESERVED_FRIED_CHICKEN: _HardwareModel.ValueType # 93
"""
Reserved Fried Chicken ID for future use
"""
HELTEC_MESH_POCKET: _HardwareModel.ValueType # 94
"""
Heltec Magnetic Power Bank with Meshtastic compatible
"""
SEEED_SOLAR_NODE: _HardwareModel.ValueType # 95
"""
Seeed Solar Node
"""
NOMADSTAR_METEOR_PRO: _HardwareModel.ValueType # 96
"""
NomadStar Meteor Pro https://nomadstar.ch/
"""
CROWPANEL: _HardwareModel.ValueType # 97
"""
Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin
"""
LINK_32: _HardwareModel.ValueType # 98
"""
Lilygo LINK32 board with sensors
"""
SEEED_WIO_TRACKER_L1: _HardwareModel.ValueType # 99
"""
Seeed Tracker L1
"""
SEEED_WIO_TRACKER_L1_EINK: _HardwareModel.ValueType # 100
"""
Seeed Tracker L1 EINK driver
"""
QWANTZ_TINY_ARMS: _HardwareModel.ValueType # 101
"""
Reserved ID for future and past use
"""
T_DECK_PRO: _HardwareModel.ValueType # 102
"""
Lilygo T-Deck Pro
"""
T_LORA_PAGER: _HardwareModel.ValueType # 103
"""
Lilygo TLora Pager
"""
GAT562_MESH_TRIAL_TRACKER: _HardwareModel.ValueType # 104
"""
GAT562 Mesh Trial Tracker
"""
WISMESH_TAG: _HardwareModel.ValueType # 105
"""
RAKwireless WisMesh Tag
"""
RAK3312: _HardwareModel.ValueType # 106
"""
RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/
"""
THINKNODE_M5: _HardwareModel.ValueType # 107
"""
Elecrow ThinkNode M5 https://www.elecrow.com/wiki/ThinkNode_M5_Meshtastic_LoRa_Signal_Transceiver_ESP32-S3.html
"""
HELTEC_MESH_SOLAR: _HardwareModel.ValueType # 108
"""
MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
https://heltec.org/project/meshsolar/
"""
T_ECHO_LITE: _HardwareModel.ValueType # 109
"""
Lilygo T-Echo Lite
"""
PRIVATE_HW: _HardwareModel.ValueType # 255
"""
------------------------------------------------------------------------------------------------------------------------------------------
@@ -680,7 +768,7 @@ CDEBYTE EoRa-S3 board using their own MM modules, clone of LILYGO T3S3
"""
TWC_MESH_V4: HardwareModel.ValueType # 62
"""
TWC_MESH_V4
TWC_MESH_V4
Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS
"""
NRF52_PROMICRO_DIY: HardwareModel.ValueType # 63
@@ -787,6 +875,94 @@ MESHLINK: HardwareModel.ValueType # 87
MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog
https://www.loraitalia.it
"""
XIAO_NRF52_KIT: HardwareModel.ValueType # 88
"""
Seeed XIAO nRF52840 + Wio SX1262 kit
"""
THINKNODE_M1: HardwareModel.ValueType # 89
"""
Elecrow ThinkNode M1 & M2
https://www.elecrow.com/wiki/ThinkNode-M1_Transceiver_Device(Meshtastic)_Power_By_nRF52840.html
https://www.elecrow.com/wiki/ThinkNode-M2_Transceiver_Device(Meshtastic)_Power_By_NRF52840.html (this actually uses ESP32-S3)
"""
THINKNODE_M2: HardwareModel.ValueType # 90
T_ETH_ELITE: HardwareModel.ValueType # 91
"""
Lilygo T-ETH-Elite
"""
HELTEC_SENSOR_HUB: HardwareModel.ValueType # 92
"""
Heltec HRI-3621 industrial probe
"""
RESERVED_FRIED_CHICKEN: HardwareModel.ValueType # 93
"""
Reserved Fried Chicken ID for future use
"""
HELTEC_MESH_POCKET: HardwareModel.ValueType # 94
"""
Heltec Magnetic Power Bank with Meshtastic compatible
"""
SEEED_SOLAR_NODE: HardwareModel.ValueType # 95
"""
Seeed Solar Node
"""
NOMADSTAR_METEOR_PRO: HardwareModel.ValueType # 96
"""
NomadStar Meteor Pro https://nomadstar.ch/
"""
CROWPANEL: HardwareModel.ValueType # 97
"""
Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin
"""
LINK_32: HardwareModel.ValueType # 98
"""
Lilygo LINK32 board with sensors
"""
SEEED_WIO_TRACKER_L1: HardwareModel.ValueType # 99
"""
Seeed Tracker L1
"""
SEEED_WIO_TRACKER_L1_EINK: HardwareModel.ValueType # 100
"""
Seeed Tracker L1 EINK driver
"""
QWANTZ_TINY_ARMS: HardwareModel.ValueType # 101
"""
Reserved ID for future and past use
"""
T_DECK_PRO: HardwareModel.ValueType # 102
"""
Lilygo T-Deck Pro
"""
T_LORA_PAGER: HardwareModel.ValueType # 103
"""
Lilygo TLora Pager
"""
GAT562_MESH_TRIAL_TRACKER: HardwareModel.ValueType # 104
"""
GAT562 Mesh Trial Tracker
"""
WISMESH_TAG: HardwareModel.ValueType # 105
"""
RAKwireless WisMesh Tag
"""
RAK3312: HardwareModel.ValueType # 106
"""
RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/
"""
THINKNODE_M5: HardwareModel.ValueType # 107
"""
Elecrow ThinkNode M5 https://www.elecrow.com/wiki/ThinkNode_M5_Meshtastic_LoRa_Signal_Transceiver_ESP32-S3.html
"""
HELTEC_MESH_SOLAR: HardwareModel.ValueType # 108
"""
MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
https://heltec.org/project/meshsolar/
"""
T_ECHO_LITE: HardwareModel.ValueType # 109
"""
Lilygo T-Echo Lite
"""
PRIVATE_HW: HardwareModel.ValueType # 255
"""
------------------------------------------------------------------------------------------------------------------------------------------
@@ -968,6 +1144,77 @@ If you see this failure in the field please post in the forum because we are int
"""
global___CriticalErrorCode = CriticalErrorCode
class _FirmwareEdition:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _FirmwareEditionEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_FirmwareEdition.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
VANILLA: _FirmwareEdition.ValueType # 0
"""
Vanilla firmware
"""
SMART_CITIZEN: _FirmwareEdition.ValueType # 1
"""
Firmware for use in the Smart Citizen environmental monitoring network
"""
OPEN_SAUCE: _FirmwareEdition.ValueType # 16
"""
Open Sauce, the maker conference held yearly in CA
"""
DEFCON: _FirmwareEdition.ValueType # 17
"""
DEFCON, the yearly hacker conference
"""
BURNING_MAN: _FirmwareEdition.ValueType # 18
"""
Burning Man, the yearly hippie gathering in the desert
"""
HAMVENTION: _FirmwareEdition.ValueType # 19
"""
Hamvention, the Dayton amateur radio convention
"""
DIY_EDITION: _FirmwareEdition.ValueType # 127
"""
Placeholder for DIY and unofficial events
"""
class FirmwareEdition(_FirmwareEdition, metaclass=_FirmwareEditionEnumTypeWrapper):
"""
Enum to indicate to clients whether this firmware is a special firmware build, like an event.
The first 16 values are reserved for non-event special firmwares, like the Smart Citizen use case.
"""
VANILLA: FirmwareEdition.ValueType # 0
"""
Vanilla firmware
"""
SMART_CITIZEN: FirmwareEdition.ValueType # 1
"""
Firmware for use in the Smart Citizen environmental monitoring network
"""
OPEN_SAUCE: FirmwareEdition.ValueType # 16
"""
Open Sauce, the maker conference held yearly in CA
"""
DEFCON: FirmwareEdition.ValueType # 17
"""
DEFCON, the yearly hacker conference
"""
BURNING_MAN: FirmwareEdition.ValueType # 18
"""
Burning Man, the yearly hippie gathering in the desert
"""
HAMVENTION: FirmwareEdition.ValueType # 19
"""
Hamvention, the Dayton amateur radio convention
"""
DIY_EDITION: FirmwareEdition.ValueType # 127
"""
Placeholder for DIY and unofficial events
"""
global___FirmwareEdition = FirmwareEdition
class _ExcludedModules:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
@@ -1030,6 +1277,14 @@ class _ExcludedModulesEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper
"""
Paxcounter module
"""
BLUETOOTH_CONFIG: _ExcludedModules.ValueType # 8192
"""
Bluetooth config (not technically a module, but used to indicate bluetooth capabilities)
"""
NETWORK_CONFIG: _ExcludedModules.ValueType # 16384
"""
Network config (not technically a module, but used to indicate network capabilities)
"""
class ExcludedModules(_ExcludedModules, metaclass=_ExcludedModulesEnumTypeWrapper):
"""
@@ -1094,6 +1349,14 @@ PAXCOUNTER_CONFIG: ExcludedModules.ValueType # 4096
"""
Paxcounter module
"""
BLUETOOTH_CONFIG: ExcludedModules.ValueType # 8192
"""
Bluetooth config (not technically a module, but used to indicate bluetooth capabilities)
"""
NETWORK_CONFIG: ExcludedModules.ValueType # 16384
"""
Network config (not technically a module, but used to indicate network capabilities)
"""
global___ExcludedModules = ExcludedModules
@typing.final
@@ -1418,6 +1681,7 @@ class User(google.protobuf.message.Message):
IS_LICENSED_FIELD_NUMBER: builtins.int
ROLE_FIELD_NUMBER: builtins.int
PUBLIC_KEY_FIELD_NUMBER: builtins.int
IS_UNMESSAGABLE_FIELD_NUMBER: builtins.int
id: builtins.str
"""
A globally unique ID string for this user.
@@ -1462,6 +1726,10 @@ class User(google.protobuf.message.Message):
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.
"""
is_unmessagable: builtins.bool
"""
Whether or not the node can be messaged
"""
def __init__(
self,
*,
@@ -1473,8 +1741,11 @@ class User(google.protobuf.message.Message):
is_licensed: builtins.bool = ...,
role: meshtastic.protobuf.config_pb2.Config.DeviceConfig.Role.ValueType = ...,
public_key: builtins.bytes = ...,
is_unmessagable: builtins.bool | 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", "public_key", b"public_key", "role", b"role", "short_name", b"short_name"]) -> None: ...
def HasField(self, field_name: typing.Literal["_is_unmessagable", b"_is_unmessagable", "is_unmessagable", b"is_unmessagable"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_is_unmessagable", b"_is_unmessagable", "hw_model", b"hw_model", "id", b"id", "is_licensed", b"is_licensed", "is_unmessagable", b"is_unmessagable", "long_name", b"long_name", "macaddr", b"macaddr", "public_key", b"public_key", "role", b"role", "short_name", b"short_name"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["_is_unmessagable", b"_is_unmessagable"]) -> typing.Literal["is_unmessagable"] | None: ...
global___User = User
@@ -1606,6 +1877,11 @@ class Routing(google.protobuf.message.Message):
"""
Admin packet sent using PKC, but not from a public key on the admin key list
"""
RATE_LIMIT_EXCEEDED: Routing._Error.ValueType # 38
"""
Airtime fairness rate limit exceeded for a packet
This typically enforced per portnum and is used to prevent a single node from monopolizing airtime
"""
class Error(_Error, metaclass=_ErrorEnumTypeWrapper):
"""
@@ -1679,6 +1955,11 @@ class Routing(google.protobuf.message.Message):
"""
Admin packet sent using PKC, but not from a public key on the admin key list
"""
RATE_LIMIT_EXCEEDED: Routing.Error.ValueType # 38
"""
Airtime fairness rate limit exceeded for a packet
This typically enforced per portnum and is used to prevent a single node from monopolizing airtime
"""
ROUTE_REQUEST_FIELD_NUMBER: builtins.int
ROUTE_REPLY_FIELD_NUMBER: builtins.int
@@ -1797,6 +2078,41 @@ class Data(google.protobuf.message.Message):
global___Data = Data
@typing.final
class KeyVerification(google.protobuf.message.Message):
"""
The actual over-the-mesh message doing KeyVerification
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NONCE_FIELD_NUMBER: builtins.int
HASH1_FIELD_NUMBER: builtins.int
HASH2_FIELD_NUMBER: builtins.int
nonce: builtins.int
"""
random value Selected by the requesting node
"""
hash1: builtins.bytes
"""
The final authoritative hash, only to be sent by NodeA at the end of the handshake
"""
hash2: builtins.bytes
"""
The intermediary hash (actually derived from hash1),
sent from NodeB to NodeA in response to the initial message.
"""
def __init__(
self,
*,
nonce: builtins.int = ...,
hash1: builtins.bytes = ...,
hash2: builtins.bytes = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["hash1", b"hash1", "hash2", b"hash2", "nonce", b"nonce"]) -> None: ...
global___KeyVerification = KeyVerification
@typing.final
class Waypoint(google.protobuf.message.Message):
"""
@@ -2074,6 +2390,83 @@ class MeshPacket(google.protobuf.message.Message):
The message is delayed and was originally a direct message
"""
class _TransportMechanism:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _TransportMechanismEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[MeshPacket._TransportMechanism.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
TRANSPORT_INTERNAL: MeshPacket._TransportMechanism.ValueType # 0
"""
The default case is that the node generated a packet itself
"""
TRANSPORT_LORA: MeshPacket._TransportMechanism.ValueType # 1
"""
Arrived via the primary LoRa radio
"""
TRANSPORT_LORA_ALT1: MeshPacket._TransportMechanism.ValueType # 2
"""
Arrived via a secondary LoRa radio
"""
TRANSPORT_LORA_ALT2: MeshPacket._TransportMechanism.ValueType # 3
"""
Arrived via a tertiary LoRa radio
"""
TRANSPORT_LORA_ALT3: MeshPacket._TransportMechanism.ValueType # 4
"""
Arrived via a quaternary LoRa radio
"""
TRANSPORT_MQTT: MeshPacket._TransportMechanism.ValueType # 5
"""
Arrived via an MQTT connection
"""
TRANSPORT_MULTICAST_UDP: MeshPacket._TransportMechanism.ValueType # 6
"""
Arrived via Multicast UDP
"""
TRANSPORT_API: MeshPacket._TransportMechanism.ValueType # 7
"""
Arrived via API connection
"""
class TransportMechanism(_TransportMechanism, metaclass=_TransportMechanismEnumTypeWrapper):
"""
Enum to identify which transport mechanism this packet arrived over
"""
TRANSPORT_INTERNAL: MeshPacket.TransportMechanism.ValueType # 0
"""
The default case is that the node generated a packet itself
"""
TRANSPORT_LORA: MeshPacket.TransportMechanism.ValueType # 1
"""
Arrived via the primary LoRa radio
"""
TRANSPORT_LORA_ALT1: MeshPacket.TransportMechanism.ValueType # 2
"""
Arrived via a secondary LoRa radio
"""
TRANSPORT_LORA_ALT2: MeshPacket.TransportMechanism.ValueType # 3
"""
Arrived via a tertiary LoRa radio
"""
TRANSPORT_LORA_ALT3: MeshPacket.TransportMechanism.ValueType # 4
"""
Arrived via a quaternary LoRa radio
"""
TRANSPORT_MQTT: MeshPacket.TransportMechanism.ValueType # 5
"""
Arrived via an MQTT connection
"""
TRANSPORT_MULTICAST_UDP: MeshPacket.TransportMechanism.ValueType # 6
"""
Arrived via Multicast UDP
"""
TRANSPORT_API: MeshPacket.TransportMechanism.ValueType # 7
"""
Arrived via API connection
"""
FROM_FIELD_NUMBER: builtins.int
TO_FIELD_NUMBER: builtins.int
CHANNEL_FIELD_NUMBER: builtins.int
@@ -2094,6 +2487,7 @@ class MeshPacket(google.protobuf.message.Message):
NEXT_HOP_FIELD_NUMBER: builtins.int
RELAY_NODE_FIELD_NUMBER: builtins.int
TX_AFTER_FIELD_NUMBER: builtins.int
TRANSPORT_MECHANISM_FIELD_NUMBER: builtins.int
to: builtins.int
"""
The (immediate) destination for this packet
@@ -2187,7 +2581,7 @@ class MeshPacket(google.protobuf.message.Message):
"""
next_hop: builtins.int
"""
Last byte of the node number of the node that should be used as the next hop in routing.
Last byte of the node number of the node that should be used as the next hop in routing.
Set by the firmware internally, clients are not supposed to set this.
"""
relay_node: builtins.int
@@ -2201,6 +2595,10 @@ class MeshPacket(google.protobuf.message.Message):
Timestamp after which this packet may be sent.
Set by the firmware internally, clients are not supposed to set this.
"""
transport_mechanism: global___MeshPacket.TransportMechanism.ValueType
"""
Indicates which transport mechanism this packet arrived over
"""
@property
def decoded(self) -> global___Data:
"""
@@ -2229,9 +2627,10 @@ class MeshPacket(google.protobuf.message.Message):
next_hop: builtins.int = ...,
relay_node: builtins.int = ...,
tx_after: builtins.int = ...,
transport_mechanism: global___MeshPacket.TransportMechanism.ValueType = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["decoded", b"decoded", "encrypted", b"encrypted", "payload_variant", b"payload_variant"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["channel", b"channel", "decoded", b"decoded", "delayed", b"delayed", "encrypted", b"encrypted", "from", b"from", "hop_limit", b"hop_limit", "hop_start", b"hop_start", "id", b"id", "next_hop", b"next_hop", "payload_variant", b"payload_variant", "pki_encrypted", b"pki_encrypted", "priority", b"priority", "public_key", b"public_key", "relay_node", b"relay_node", "rx_rssi", b"rx_rssi", "rx_snr", b"rx_snr", "rx_time", b"rx_time", "to", b"to", "tx_after", b"tx_after", "via_mqtt", b"via_mqtt", "want_ack", b"want_ack"]) -> None: ...
def ClearField(self, field_name: typing.Literal["channel", b"channel", "decoded", b"decoded", "delayed", b"delayed", "encrypted", b"encrypted", "from", b"from", "hop_limit", b"hop_limit", "hop_start", b"hop_start", "id", b"id", "next_hop", b"next_hop", "payload_variant", b"payload_variant", "pki_encrypted", b"pki_encrypted", "priority", b"priority", "public_key", b"public_key", "relay_node", b"relay_node", "rx_rssi", b"rx_rssi", "rx_snr", b"rx_snr", "rx_time", b"rx_time", "to", b"to", "transport_mechanism", b"transport_mechanism", "tx_after", b"tx_after", "via_mqtt", b"via_mqtt", "want_ack", b"want_ack"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["decoded", "encrypted"] | None: ...
global___MeshPacket = MeshPacket
@@ -2270,6 +2669,7 @@ class NodeInfo(google.protobuf.message.Message):
HOPS_AWAY_FIELD_NUMBER: builtins.int
IS_FAVORITE_FIELD_NUMBER: builtins.int
IS_IGNORED_FIELD_NUMBER: builtins.int
IS_KEY_MANUALLY_VERIFIED_FIELD_NUMBER: builtins.int
num: builtins.int
"""
The node number
@@ -2311,6 +2711,12 @@ class NodeInfo(google.protobuf.message.Message):
True if node is in our ignored list
Persists between NodeDB internal clean ups
"""
is_key_manually_verified: builtins.bool
"""
True if node public key has been verified.
Persists between NodeDB internal clean ups
LSB 0 of the bitfield
"""
@property
def user(self) -> global___User:
"""
@@ -2344,9 +2750,10 @@ class NodeInfo(google.protobuf.message.Message):
hops_away: builtins.int | None = ...,
is_favorite: builtins.bool = ...,
is_ignored: builtins.bool = ...,
is_key_manually_verified: builtins.bool = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "position", b"position", "user", b"user"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "last_heard", b"last_heard", "num", b"num", "position", b"position", "snr", b"snr", "user", b"user", "via_mqtt", b"via_mqtt"]) -> None: ...
def ClearField(self, field_name: typing.Literal["_hops_away", b"_hops_away", "channel", b"channel", "device_metrics", b"device_metrics", "hops_away", b"hops_away", "is_favorite", b"is_favorite", "is_ignored", b"is_ignored", "is_key_manually_verified", b"is_key_manually_verified", "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
@@ -2366,6 +2773,8 @@ class MyNodeInfo(google.protobuf.message.Message):
MIN_APP_VERSION_FIELD_NUMBER: builtins.int
DEVICE_ID_FIELD_NUMBER: builtins.int
PIO_ENV_FIELD_NUMBER: builtins.int
FIRMWARE_EDITION_FIELD_NUMBER: builtins.int
NODEDB_COUNT_FIELD_NUMBER: builtins.int
my_node_num: builtins.int
"""
Tells the phone what our node number is, default starting value is
@@ -2389,6 +2798,15 @@ class MyNodeInfo(google.protobuf.message.Message):
"""
The PlatformIO environment used to build this firmware
"""
firmware_edition: global___FirmwareEdition.ValueType
"""
The indicator for whether this device is running event firmware and which
"""
nodedb_count: builtins.int
"""
The number of nodes in the nodedb.
This is used by the phone to know how many NodeInfo packets to expect on want_config
"""
def __init__(
self,
*,
@@ -2397,8 +2815,10 @@ class MyNodeInfo(google.protobuf.message.Message):
min_app_version: builtins.int = ...,
device_id: builtins.bytes = ...,
pio_env: builtins.str = ...,
firmware_edition: global___FirmwareEdition.ValueType = ...,
nodedb_count: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["device_id", b"device_id", "min_app_version", b"min_app_version", "my_node_num", b"my_node_num", "pio_env", b"pio_env", "reboot_count", b"reboot_count"]) -> None: ...
def ClearField(self, field_name: typing.Literal["device_id", b"device_id", "firmware_edition", b"firmware_edition", "min_app_version", b"min_app_version", "my_node_num", b"my_node_num", "nodedb_count", b"nodedb_count", "pio_env", b"pio_env", "reboot_count", b"reboot_count"]) -> None: ...
global___MyNodeInfo = MyNodeInfo
@@ -2718,6 +3138,11 @@ class ClientNotification(google.protobuf.message.Message):
TIME_FIELD_NUMBER: builtins.int
LEVEL_FIELD_NUMBER: builtins.int
MESSAGE_FIELD_NUMBER: builtins.int
KEY_VERIFICATION_NUMBER_INFORM_FIELD_NUMBER: builtins.int
KEY_VERIFICATION_NUMBER_REQUEST_FIELD_NUMBER: builtins.int
KEY_VERIFICATION_FINAL_FIELD_NUMBER: builtins.int
DUPLICATED_PUBLIC_KEY_FIELD_NUMBER: builtins.int
LOW_ENTROPY_KEY_FIELD_NUMBER: builtins.int
reply_id: builtins.int
"""
The id of the packet we're notifying in response to
@@ -2734,6 +3159,16 @@ class ClientNotification(google.protobuf.message.Message):
"""
The message body of the notification
"""
@property
def key_verification_number_inform(self) -> global___KeyVerificationNumberInform: ...
@property
def key_verification_number_request(self) -> global___KeyVerificationNumberRequest: ...
@property
def key_verification_final(self) -> global___KeyVerificationFinal: ...
@property
def duplicated_public_key(self) -> global___DuplicatedPublicKey: ...
@property
def low_entropy_key(self) -> global___LowEntropyKey: ...
def __init__(
self,
*,
@@ -2741,13 +3176,104 @@ class ClientNotification(google.protobuf.message.Message):
time: builtins.int = ...,
level: global___LogRecord.Level.ValueType = ...,
message: builtins.str = ...,
key_verification_number_inform: global___KeyVerificationNumberInform | None = ...,
key_verification_number_request: global___KeyVerificationNumberRequest | None = ...,
key_verification_final: global___KeyVerificationFinal | None = ...,
duplicated_public_key: global___DuplicatedPublicKey | None = ...,
low_entropy_key: global___LowEntropyKey | None = ...,
) -> 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 HasField(self, field_name: typing.Literal["_reply_id", b"_reply_id", "duplicated_public_key", b"duplicated_public_key", "key_verification_final", b"key_verification_final", "key_verification_number_inform", b"key_verification_number_inform", "key_verification_number_request", b"key_verification_number_request", "low_entropy_key", b"low_entropy_key", "payload_variant", b"payload_variant", "reply_id", b"reply_id"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_reply_id", b"_reply_id", "duplicated_public_key", b"duplicated_public_key", "key_verification_final", b"key_verification_final", "key_verification_number_inform", b"key_verification_number_inform", "key_verification_number_request", b"key_verification_number_request", "level", b"level", "low_entropy_key", b"low_entropy_key", "message", b"message", "payload_variant", b"payload_variant", "reply_id", b"reply_id", "time", b"time"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_reply_id", b"_reply_id"]) -> typing.Literal["reply_id"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["key_verification_number_inform", "key_verification_number_request", "key_verification_final", "duplicated_public_key", "low_entropy_key"] | None: ...
global___ClientNotification = ClientNotification
@typing.final
class KeyVerificationNumberInform(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NONCE_FIELD_NUMBER: builtins.int
REMOTE_LONGNAME_FIELD_NUMBER: builtins.int
SECURITY_NUMBER_FIELD_NUMBER: builtins.int
nonce: builtins.int
remote_longname: builtins.str
security_number: builtins.int
def __init__(
self,
*,
nonce: builtins.int = ...,
remote_longname: builtins.str = ...,
security_number: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["nonce", b"nonce", "remote_longname", b"remote_longname", "security_number", b"security_number"]) -> None: ...
global___KeyVerificationNumberInform = KeyVerificationNumberInform
@typing.final
class KeyVerificationNumberRequest(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NONCE_FIELD_NUMBER: builtins.int
REMOTE_LONGNAME_FIELD_NUMBER: builtins.int
nonce: builtins.int
remote_longname: builtins.str
def __init__(
self,
*,
nonce: builtins.int = ...,
remote_longname: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["nonce", b"nonce", "remote_longname", b"remote_longname"]) -> None: ...
global___KeyVerificationNumberRequest = KeyVerificationNumberRequest
@typing.final
class KeyVerificationFinal(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NONCE_FIELD_NUMBER: builtins.int
REMOTE_LONGNAME_FIELD_NUMBER: builtins.int
ISSENDER_FIELD_NUMBER: builtins.int
VERIFICATION_CHARACTERS_FIELD_NUMBER: builtins.int
nonce: builtins.int
remote_longname: builtins.str
isSender: builtins.bool
verification_characters: builtins.str
def __init__(
self,
*,
nonce: builtins.int = ...,
remote_longname: builtins.str = ...,
isSender: builtins.bool = ...,
verification_characters: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["isSender", b"isSender", "nonce", b"nonce", "remote_longname", b"remote_longname", "verification_characters", b"verification_characters"]) -> None: ...
global___KeyVerificationFinal = KeyVerificationFinal
@typing.final
class DuplicatedPublicKey(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
def __init__(
self,
) -> None: ...
global___DuplicatedPublicKey = DuplicatedPublicKey
@typing.final
class LowEntropyKey(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
def __init__(
self,
) -> None: ...
global___LowEntropyKey = LowEntropyKey
@typing.final
class FileInfo(google.protobuf.message.Message):
"""
@@ -3058,9 +3584,17 @@ class Heartbeat(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NONCE_FIELD_NUMBER: builtins.int
nonce: builtins.int
"""
The nonce of the heartbeat message
"""
def __init__(
self,
*,
nonce: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["nonce", b"nonce"]) -> None: ...
global___Heartbeat = Heartbeat

View File

File diff suppressed because one or more lines are too long

View File

@@ -165,6 +165,7 @@ class ModuleConfig(google.protobuf.message.Message):
PUBLISH_INTERVAL_SECS_FIELD_NUMBER: builtins.int
POSITION_PRECISION_FIELD_NUMBER: builtins.int
SHOULD_REPORT_LOCATION_FIELD_NUMBER: builtins.int
publish_interval_secs: builtins.int
"""
How often we should report our info to the map (in seconds)
@@ -173,13 +174,18 @@ class ModuleConfig(google.protobuf.message.Message):
"""
Bits of precision for the location sent (default of 32 is full precision).
"""
should_report_location: builtins.bool
"""
Whether we have opted-in to report our location to the map
"""
def __init__(
self,
*,
publish_interval_secs: builtins.int = ...,
position_precision: builtins.int = ...,
should_report_location: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["position_precision", b"position_precision", "publish_interval_secs", b"publish_interval_secs"]) -> None: ...
def ClearField(self, field_name: typing.Literal["position_precision", b"position_precision", "publish_interval_secs", b"publish_interval_secs", "should_report_location", b"should_report_location"]) -> None: ...
@typing.final
class RemoteHardwareConfig(google.protobuf.message.Message):
@@ -554,6 +560,14 @@ class ModuleConfig(google.protobuf.message.Message):
"""NMEA messages specifically tailored for CalTopo"""
WS85: ModuleConfig.SerialConfig._Serial_Mode.ValueType # 6
"""Ecowitt WS85 weather station"""
VE_DIRECT: ModuleConfig.SerialConfig._Serial_Mode.ValueType # 7
"""VE.Direct is a serial protocol used by Victron Energy products
https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable
"""
MS_CONFIG: ModuleConfig.SerialConfig._Serial_Mode.ValueType # 8
"""Used to configure and view some parameters of MeshSolar.
https://heltec.org/project/meshsolar/
"""
class Serial_Mode(_Serial_Mode, metaclass=_Serial_ModeEnumTypeWrapper):
"""
@@ -569,6 +583,14 @@ class ModuleConfig(google.protobuf.message.Message):
"""NMEA messages specifically tailored for CalTopo"""
WS85: ModuleConfig.SerialConfig.Serial_Mode.ValueType # 6
"""Ecowitt WS85 weather station"""
VE_DIRECT: ModuleConfig.SerialConfig.Serial_Mode.ValueType # 7
"""VE.Direct is a serial protocol used by Victron Energy products
https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable
"""
MS_CONFIG: ModuleConfig.SerialConfig.Serial_Mode.ValueType # 8
"""Used to configure and view some parameters of MeshSolar.
https://heltec.org/project/meshsolar/
"""
ENABLED_FIELD_NUMBER: builtins.int
ECHO_FIELD_NUMBER: builtins.int
@@ -802,6 +824,7 @@ class ModuleConfig(google.protobuf.message.Message):
ENABLED_FIELD_NUMBER: builtins.int
SENDER_FIELD_NUMBER: builtins.int
SAVE_FIELD_NUMBER: builtins.int
CLEAR_ON_REBOOT_FIELD_NUMBER: builtins.int
enabled: builtins.bool
"""
Enable the Range Test Module
@@ -815,14 +838,20 @@ class ModuleConfig(google.protobuf.message.Message):
Bool value indicating that this node should save a RangeTest.csv file.
ESP32 Only
"""
clear_on_reboot: builtins.bool
"""
Bool indicating that the node should cleanup / destroy it's RangeTest.csv file.
ESP32 Only
"""
def __init__(
self,
*,
enabled: builtins.bool = ...,
sender: builtins.int = ...,
save: builtins.bool = ...,
clear_on_reboot: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["enabled", b"enabled", "save", b"save", "sender", b"sender"]) -> None: ...
def ClearField(self, field_name: typing.Literal["clear_on_reboot", b"clear_on_reboot", "enabled", b"enabled", "save", b"save", "sender", b"sender"]) -> None: ...
@typing.final
class TelemetryConfig(google.protobuf.message.Message):

View File

@@ -15,7 +15,7 @@ from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/mqtt.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\x1emeshtastic/protobuf/mesh.proto\"j\n\x0fServiceEnvelope\x12/\n\x06packet\x18\x01 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\t\"\xe0\x03\n\tMapReport\x12\x11\n\tlong_name\x18\x01 \x01(\t\x12\x12\n\nshort_name\x18\x02 \x01(\t\x12;\n\x04role\x18\x03 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x34\n\x08hw_model\x18\x04 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x18\n\x10\x66irmware_version\x18\x05 \x01(\t\x12\x41\n\x06region\x18\x06 \x01(\x0e\x32\x31.meshtastic.protobuf.Config.LoRaConfig.RegionCode\x12H\n\x0cmodem_preset\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.LoRaConfig.ModemPreset\x12\x1b\n\x13has_default_channel\x18\x08 \x01(\x08\x12\x12\n\nlatitude_i\x18\t \x01(\x0f\x12\x13\n\x0blongitude_i\x18\n \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x0b \x01(\x05\x12\x1a\n\x12position_precision\x18\x0c \x01(\r\x12\x1e\n\x16num_online_local_nodes\x18\r \x01(\rB_\n\x13\x63om.geeksville.meshB\nMQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtastic/protobuf/mqtt.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\x1emeshtastic/protobuf/mesh.proto\"j\n\x0fServiceEnvelope\x12/\n\x06packet\x18\x01 \x01(\x0b\x32\x1f.meshtastic.protobuf.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\t\"\x83\x04\n\tMapReport\x12\x11\n\tlong_name\x18\x01 \x01(\t\x12\x12\n\nshort_name\x18\x02 \x01(\t\x12;\n\x04role\x18\x03 \x01(\x0e\x32-.meshtastic.protobuf.Config.DeviceConfig.Role\x12\x34\n\x08hw_model\x18\x04 \x01(\x0e\x32\".meshtastic.protobuf.HardwareModel\x12\x18\n\x10\x66irmware_version\x18\x05 \x01(\t\x12\x41\n\x06region\x18\x06 \x01(\x0e\x32\x31.meshtastic.protobuf.Config.LoRaConfig.RegionCode\x12H\n\x0cmodem_preset\x18\x07 \x01(\x0e\x32\x32.meshtastic.protobuf.Config.LoRaConfig.ModemPreset\x12\x1b\n\x13has_default_channel\x18\x08 \x01(\x08\x12\x12\n\nlatitude_i\x18\t \x01(\x0f\x12\x13\n\x0blongitude_i\x18\n \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x0b \x01(\x05\x12\x1a\n\x12position_precision\x18\x0c \x01(\r\x12\x1e\n\x16num_online_local_nodes\x18\r \x01(\r\x12!\n\x19has_opted_report_location\x18\x0e \x01(\x08\x42_\n\x13\x63om.geeksville.meshB\nMQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -26,5 +26,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_globals['_SERVICEENVELOPE']._serialized_start=121
_globals['_SERVICEENVELOPE']._serialized_end=227
_globals['_MAPREPORT']._serialized_start=230
_globals['_MAPREPORT']._serialized_end=710
_globals['_MAPREPORT']._serialized_end=745
# @@protoc_insertion_point(module_scope)

View File

@@ -72,6 +72,7 @@ class MapReport(google.protobuf.message.Message):
ALTITUDE_FIELD_NUMBER: builtins.int
POSITION_PRECISION_FIELD_NUMBER: builtins.int
NUM_ONLINE_LOCAL_NODES_FIELD_NUMBER: builtins.int
HAS_OPTED_REPORT_LOCATION_FIELD_NUMBER: builtins.int
long_name: builtins.str
"""
A full name for this user, i.e. "Kevin Hester"
@@ -126,6 +127,11 @@ class MapReport(google.protobuf.message.Message):
"""
Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT)
"""
has_opted_report_location: builtins.bool
"""
User has opted in to share their location (map report) with the mqtt server
Controlled by map_report.should_report_location
"""
def __init__(
self,
*,
@@ -142,7 +148,8 @@ class MapReport(google.protobuf.message.Message):
altitude: builtins.int = ...,
position_precision: builtins.int = ...,
num_online_local_nodes: builtins.int = ...,
has_opted_report_location: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["altitude", b"altitude", "firmware_version", b"firmware_version", "has_default_channel", b"has_default_channel", "hw_model", b"hw_model", "latitude_i", b"latitude_i", "long_name", b"long_name", "longitude_i", b"longitude_i", "modem_preset", b"modem_preset", "num_online_local_nodes", b"num_online_local_nodes", "position_precision", b"position_precision", "region", b"region", "role", b"role", "short_name", b"short_name"]) -> None: ...
def ClearField(self, field_name: typing.Literal["altitude", b"altitude", "firmware_version", b"firmware_version", "has_default_channel", b"has_default_channel", "has_opted_report_location", b"has_opted_report_location", "hw_model", b"hw_model", "latitude_i", b"latitude_i", "long_name", b"long_name", "longitude_i", b"longitude_i", "modem_preset", b"modem_preset", "num_online_local_nodes", b"num_online_local_nodes", "position_precision", b"position_precision", "region", b"region", "role", b"role", "short_name", b"short_name"]) -> None: ...
global___MapReport = MapReport

35
meshtastic/protobuf/nanopb_pb2.py generated Normal file
View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: meshtastic/protobuf/nanopb.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/nanopb.proto\x1a google/protobuf/descriptor.proto\"\xa4\x07\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x19\n\x0bsort_by_tag\x18\x1c \x01(\x08:\x04true\x12.\n\rfallback_type\x18\x1d \x01(\x0e\x32\n.FieldType:\x0b\x46T_CALLBACK*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB>\n\x18\x66i.kapsi.koti.jpa.nanopbZ\"github.com/meshtastic/go/generated')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.nanopb_pb2', _globals)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\030fi.kapsi.koti.jpa.nanopbZ\"github.com/meshtastic/go/generated'
_globals['_FIELDTYPE']._serialized_start=1005
_globals['_FIELDTYPE']._serialized_end=1110
_globals['_INTSIZE']._serialized_start=1112
_globals['_INTSIZE']._serialized_end=1180
_globals['_TYPENAMEMANGLING']._serialized_start=1182
_globals['_TYPENAMEMANGLING']._serialized_end=1272
_globals['_DESCRIPTORSIZE']._serialized_start=1274
_globals['_DESCRIPTORSIZE']._serialized_end=1343
_globals['_NANOPBOPTIONS']._serialized_start=71
_globals['_NANOPBOPTIONS']._serialized_end=1003
# @@protoc_insertion_point(module_scope)

324
meshtastic/protobuf/nanopb_pb2.pyi generated Normal file
View File

@@ -0,0 +1,324 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
Custom options for defining:
- Maximum size of string/bytes
- Maximum number of elements in array
These are used by nanopb to generate statically allocable structures
for memory-limited environments.
"""
import builtins
import collections.abc
import google.protobuf.descriptor
import google.protobuf.descriptor_pb2
import google.protobuf.internal.containers
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.internal.extension_dict
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _FieldType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _FieldTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_FieldType.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
FT_DEFAULT: _FieldType.ValueType # 0
"""Automatically decide field type, generate static field if possible."""
FT_CALLBACK: _FieldType.ValueType # 1
"""Always generate a callback field."""
FT_POINTER: _FieldType.ValueType # 4
"""Always generate a dynamically allocated field."""
FT_STATIC: _FieldType.ValueType # 2
"""Generate a static field or raise an exception if not possible."""
FT_IGNORE: _FieldType.ValueType # 3
"""Ignore the field completely."""
FT_INLINE: _FieldType.ValueType # 5
"""Legacy option, use the separate 'fixed_length' option instead"""
class FieldType(_FieldType, metaclass=_FieldTypeEnumTypeWrapper): ...
FT_DEFAULT: FieldType.ValueType # 0
"""Automatically decide field type, generate static field if possible."""
FT_CALLBACK: FieldType.ValueType # 1
"""Always generate a callback field."""
FT_POINTER: FieldType.ValueType # 4
"""Always generate a dynamically allocated field."""
FT_STATIC: FieldType.ValueType # 2
"""Generate a static field or raise an exception if not possible."""
FT_IGNORE: FieldType.ValueType # 3
"""Ignore the field completely."""
FT_INLINE: FieldType.ValueType # 5
"""Legacy option, use the separate 'fixed_length' option instead"""
global___FieldType = FieldType
class _IntSize:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _IntSizeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_IntSize.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
IS_DEFAULT: _IntSize.ValueType # 0
"""Default, 32/64bit based on type in .proto"""
IS_8: _IntSize.ValueType # 8
IS_16: _IntSize.ValueType # 16
IS_32: _IntSize.ValueType # 32
IS_64: _IntSize.ValueType # 64
class IntSize(_IntSize, metaclass=_IntSizeEnumTypeWrapper): ...
IS_DEFAULT: IntSize.ValueType # 0
"""Default, 32/64bit based on type in .proto"""
IS_8: IntSize.ValueType # 8
IS_16: IntSize.ValueType # 16
IS_32: IntSize.ValueType # 32
IS_64: IntSize.ValueType # 64
global___IntSize = IntSize
class _TypenameMangling:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _TypenameManglingEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_TypenameMangling.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
M_NONE: _TypenameMangling.ValueType # 0
"""Default, no typename mangling"""
M_STRIP_PACKAGE: _TypenameMangling.ValueType # 1
"""Strip current package name"""
M_FLATTEN: _TypenameMangling.ValueType # 2
"""Only use last path component"""
M_PACKAGE_INITIALS: _TypenameMangling.ValueType # 3
"""Replace the package name by the initials"""
class TypenameMangling(_TypenameMangling, metaclass=_TypenameManglingEnumTypeWrapper): ...
M_NONE: TypenameMangling.ValueType # 0
"""Default, no typename mangling"""
M_STRIP_PACKAGE: TypenameMangling.ValueType # 1
"""Strip current package name"""
M_FLATTEN: TypenameMangling.ValueType # 2
"""Only use last path component"""
M_PACKAGE_INITIALS: TypenameMangling.ValueType # 3
"""Replace the package name by the initials"""
global___TypenameMangling = TypenameMangling
class _DescriptorSize:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _DescriptorSizeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_DescriptorSize.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
DS_AUTO: _DescriptorSize.ValueType # 0
"""Select minimal size based on field type"""
DS_1: _DescriptorSize.ValueType # 1
"""1 word; up to 15 byte fields, no arrays"""
DS_2: _DescriptorSize.ValueType # 2
"""2 words; up to 4095 byte fields, 4095 entry arrays"""
DS_4: _DescriptorSize.ValueType # 4
"""4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays"""
DS_8: _DescriptorSize.ValueType # 8
"""8 words; up to 2^32-1 entry arrays"""
class DescriptorSize(_DescriptorSize, metaclass=_DescriptorSizeEnumTypeWrapper): ...
DS_AUTO: DescriptorSize.ValueType # 0
"""Select minimal size based on field type"""
DS_1: DescriptorSize.ValueType # 1
"""1 word; up to 15 byte fields, no arrays"""
DS_2: DescriptorSize.ValueType # 2
"""2 words; up to 4095 byte fields, 4095 entry arrays"""
DS_4: DescriptorSize.ValueType # 4
"""4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays"""
DS_8: DescriptorSize.ValueType # 8
"""8 words; up to 2^32-1 entry arrays"""
global___DescriptorSize = DescriptorSize
@typing.final
class NanoPBOptions(google.protobuf.message.Message):
"""This is the inner options message, which basically defines options for
a field. When it is used in message or file scope, it applies to all
fields.
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MAX_SIZE_FIELD_NUMBER: builtins.int
MAX_LENGTH_FIELD_NUMBER: builtins.int
MAX_COUNT_FIELD_NUMBER: builtins.int
INT_SIZE_FIELD_NUMBER: builtins.int
TYPE_FIELD_NUMBER: builtins.int
LONG_NAMES_FIELD_NUMBER: builtins.int
PACKED_STRUCT_FIELD_NUMBER: builtins.int
PACKED_ENUM_FIELD_NUMBER: builtins.int
SKIP_MESSAGE_FIELD_NUMBER: builtins.int
NO_UNIONS_FIELD_NUMBER: builtins.int
MSGID_FIELD_NUMBER: builtins.int
ANONYMOUS_ONEOF_FIELD_NUMBER: builtins.int
PROTO3_FIELD_NUMBER: builtins.int
PROTO3_SINGULAR_MSGS_FIELD_NUMBER: builtins.int
ENUM_TO_STRING_FIELD_NUMBER: builtins.int
FIXED_LENGTH_FIELD_NUMBER: builtins.int
FIXED_COUNT_FIELD_NUMBER: builtins.int
SUBMSG_CALLBACK_FIELD_NUMBER: builtins.int
MANGLE_NAMES_FIELD_NUMBER: builtins.int
CALLBACK_DATATYPE_FIELD_NUMBER: builtins.int
CALLBACK_FUNCTION_FIELD_NUMBER: builtins.int
DESCRIPTORSIZE_FIELD_NUMBER: builtins.int
DEFAULT_HAS_FIELD_NUMBER: builtins.int
INCLUDE_FIELD_NUMBER: builtins.int
EXCLUDE_FIELD_NUMBER: builtins.int
PACKAGE_FIELD_NUMBER: builtins.int
TYPE_OVERRIDE_FIELD_NUMBER: builtins.int
SORT_BY_TAG_FIELD_NUMBER: builtins.int
FALLBACK_TYPE_FIELD_NUMBER: builtins.int
max_size: builtins.int
"""Allocated size for 'bytes' and 'string' fields.
For string fields, this should include the space for null terminator.
"""
max_length: builtins.int
"""Maximum length for 'string' fields. Setting this is equivalent
to setting max_size to a value of length+1.
"""
max_count: builtins.int
"""Allocated number of entries in arrays ('repeated' fields)"""
int_size: global___IntSize.ValueType
"""Size of integer fields. Can save some memory if you don't need
full 32 bits for the value.
"""
type: global___FieldType.ValueType
"""Force type of field (callback or static allocation)"""
long_names: builtins.bool
"""Use long names for enums, i.e. EnumName_EnumValue."""
packed_struct: builtins.bool
"""Add 'packed' attribute to generated structs.
Note: this cannot be used on CPUs that break on unaligned
accesses to variables.
"""
packed_enum: builtins.bool
"""Add 'packed' attribute to generated enums."""
skip_message: builtins.bool
"""Skip this message"""
no_unions: builtins.bool
"""Generate oneof fields as normal optional fields instead of union."""
msgid: builtins.int
"""integer type tag for a message"""
anonymous_oneof: builtins.bool
"""decode oneof as anonymous union"""
proto3: builtins.bool
"""Proto3 singular field does not generate a "has_" flag"""
proto3_singular_msgs: builtins.bool
"""Force proto3 messages to have no "has_" flag.
This was default behavior until nanopb-0.4.0.
"""
enum_to_string: builtins.bool
"""Generate an enum->string mapping function (can take up lots of space)."""
fixed_length: builtins.bool
"""Generate bytes arrays with fixed length"""
fixed_count: builtins.bool
"""Generate repeated field with fixed count"""
submsg_callback: builtins.bool
"""Generate message-level callback that is called before decoding submessages.
This can be used to set callback fields for submsgs inside oneofs.
"""
mangle_names: global___TypenameMangling.ValueType
"""Shorten or remove package names from type names.
This option applies only on the file level.
"""
callback_datatype: builtins.str
"""Data type for storage associated with callback fields."""
callback_function: builtins.str
"""Callback function used for encoding and decoding.
Prior to nanopb-0.4.0, the callback was specified in per-field pb_callback_t
structure. This is still supported, but does not work inside e.g. oneof or pointer
fields. Instead, a new method allows specifying a per-message callback that
will be called for all callback fields in a message type.
"""
descriptorsize: global___DescriptorSize.ValueType
"""Select the size of field descriptors. This option has to be defined
for the whole message, not per-field. Usually automatic selection is
ok, but if it results in compilation errors you can increase the field
size here.
"""
default_has: builtins.bool
"""Set default value for has_ fields."""
package: builtins.str
"""Package name that applies only for nanopb."""
type_override: google.protobuf.descriptor_pb2.FieldDescriptorProto.Type.ValueType
"""Override type of the field in generated C code. Only to be used with related field types"""
sort_by_tag: builtins.bool
"""Due to historical reasons, nanopb orders fields in structs by their tag number
instead of the order in .proto. Set this to false to keep the .proto order.
The default value will probably change to false in nanopb-0.5.0.
"""
fallback_type: global___FieldType.ValueType
"""Set the FT_DEFAULT field conversion strategy.
A field that can become a static member of a c struct (e.g. int, bool, etc)
will be a a static field.
Fields with dynamic length are converted to either a pointer or a callback.
"""
@property
def include(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]:
"""Extra files to include in generated `.pb.h`"""
@property
def exclude(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]:
"""Automatic includes to exclude from generated `.pb.h`
Same as nanopb_generator.py command line flag -x.
"""
def __init__(
self,
*,
max_size: builtins.int | None = ...,
max_length: builtins.int | None = ...,
max_count: builtins.int | None = ...,
int_size: global___IntSize.ValueType | None = ...,
type: global___FieldType.ValueType | None = ...,
long_names: builtins.bool | None = ...,
packed_struct: builtins.bool | None = ...,
packed_enum: builtins.bool | None = ...,
skip_message: builtins.bool | None = ...,
no_unions: builtins.bool | None = ...,
msgid: builtins.int | None = ...,
anonymous_oneof: builtins.bool | None = ...,
proto3: builtins.bool | None = ...,
proto3_singular_msgs: builtins.bool | None = ...,
enum_to_string: builtins.bool | None = ...,
fixed_length: builtins.bool | None = ...,
fixed_count: builtins.bool | None = ...,
submsg_callback: builtins.bool | None = ...,
mangle_names: global___TypenameMangling.ValueType | None = ...,
callback_datatype: builtins.str | None = ...,
callback_function: builtins.str | None = ...,
descriptorsize: global___DescriptorSize.ValueType | None = ...,
default_has: builtins.bool | None = ...,
include: collections.abc.Iterable[builtins.str] | None = ...,
exclude: collections.abc.Iterable[builtins.str] | None = ...,
package: builtins.str | None = ...,
type_override: google.protobuf.descriptor_pb2.FieldDescriptorProto.Type.ValueType | None = ...,
sort_by_tag: builtins.bool | None = ...,
fallback_type: global___FieldType.ValueType | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["anonymous_oneof", b"anonymous_oneof", "callback_datatype", b"callback_datatype", "callback_function", b"callback_function", "default_has", b"default_has", "descriptorsize", b"descriptorsize", "enum_to_string", b"enum_to_string", "fallback_type", b"fallback_type", "fixed_count", b"fixed_count", "fixed_length", b"fixed_length", "int_size", b"int_size", "long_names", b"long_names", "mangle_names", b"mangle_names", "max_count", b"max_count", "max_length", b"max_length", "max_size", b"max_size", "msgid", b"msgid", "no_unions", b"no_unions", "package", b"package", "packed_enum", b"packed_enum", "packed_struct", b"packed_struct", "proto3", b"proto3", "proto3_singular_msgs", b"proto3_singular_msgs", "skip_message", b"skip_message", "sort_by_tag", b"sort_by_tag", "submsg_callback", b"submsg_callback", "type", b"type", "type_override", b"type_override"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["anonymous_oneof", b"anonymous_oneof", "callback_datatype", b"callback_datatype", "callback_function", b"callback_function", "default_has", b"default_has", "descriptorsize", b"descriptorsize", "enum_to_string", b"enum_to_string", "exclude", b"exclude", "fallback_type", b"fallback_type", "fixed_count", b"fixed_count", "fixed_length", b"fixed_length", "include", b"include", "int_size", b"int_size", "long_names", b"long_names", "mangle_names", b"mangle_names", "max_count", b"max_count", "max_length", b"max_length", "max_size", b"max_size", "msgid", b"msgid", "no_unions", b"no_unions", "package", b"package", "packed_enum", b"packed_enum", "packed_struct", b"packed_struct", "proto3", b"proto3", "proto3_singular_msgs", b"proto3_singular_msgs", "skip_message", b"skip_message", "sort_by_tag", b"sort_by_tag", "submsg_callback", b"submsg_callback", "type", b"type", "type_override", b"type_override"]) -> None: ...
global___NanoPBOptions = NanoPBOptions
NANOPB_FILEOPT_FIELD_NUMBER: builtins.int
NANOPB_MSGOPT_FIELD_NUMBER: builtins.int
NANOPB_ENUMOPT_FIELD_NUMBER: builtins.int
NANOPB_FIELD_NUMBER: builtins.int
nanopb_fileopt: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FileOptions, global___NanoPBOptions]
nanopb_msgopt: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, global___NanoPBOptions]
nanopb_enumopt: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.EnumOptions, global___NanoPBOptions]
nanopb: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, global___NanoPBOptions]

View File

@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xb1\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tALERT_APP\x10\x0b\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xf6\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tALERT_APP\x10\x0b\x12\x18\n\x14KEY_VERIFICATION_APP\x10\x0c\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x18\n\x14RETICULUM_TUNNEL_APP\x10L\x12\x0f\n\x0b\x43\x41YENNE_APP\x10M\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -22,5 +22,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_PORTNUM']._serialized_start=60
_globals['_PORTNUM']._serialized_end=621
_globals['_PORTNUM']._serialized_end=690
# @@protoc_insertion_point(module_scope)

View File

@@ -97,6 +97,10 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy
"""
Same as Text Message but used for critical alerts.
"""
KEY_VERIFICATION_APP: _PortNum.ValueType # 12
"""
Module/port for handling key verification requests.
"""
REPLY_APP: _PortNum.ValueType # 32
"""
Provides a 'ping' service that replies to any packet it receives.
@@ -179,6 +183,17 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy
"""
PowerStress based monitoring support (for automated power consumption testing)
"""
RETICULUM_TUNNEL_APP: _PortNum.ValueType # 76
"""
Reticulum Network Stack Tunnel App
ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface
"""
CAYENNE_APP: _PortNum.ValueType # 77
"""
App for transporting Cayenne Low Power Payload, popular for LoRaWAN sensor nodes. Offers ability to send
arbitrary telemetry over meshtastic that is not covered by telemetry.proto
ENCODING: CayenneLLP
"""
PRIVATE_APP: _PortNum.ValueType # 256
"""
Private applications should use portnums >= 256.
@@ -286,6 +301,10 @@ ALERT_APP: PortNum.ValueType # 11
"""
Same as Text Message but used for critical alerts.
"""
KEY_VERIFICATION_APP: PortNum.ValueType # 12
"""
Module/port for handling key verification requests.
"""
REPLY_APP: PortNum.ValueType # 32
"""
Provides a 'ping' service that replies to any packet it receives.
@@ -368,6 +387,17 @@ POWERSTRESS_APP: PortNum.ValueType # 74
"""
PowerStress based monitoring support (for automated power consumption testing)
"""
RETICULUM_TUNNEL_APP: PortNum.ValueType # 76
"""
Reticulum Network Stack Tunnel App
ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface
"""
CAYENNE_APP: PortNum.ValueType # 77
"""
App for transporting Cayenne Low Power Payload, popular for LoRaWAN sensor nodes. Offers ability to send
arbitrary telemetry over meshtastic that is not covered by telemetry.proto
ENCODING: CayenneLLP
"""
PRIVATE_APP: PortNum.ValueType # 256
"""
Private applications should use portnums >= 256.

View File

File diff suppressed because one or more lines are too long

View File

@@ -167,6 +167,42 @@ class _TelemetrySensorTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wra
"""
DFRobot Gravity tipping bucket rain gauge
"""
DPS310: _TelemetrySensorType.ValueType # 36
"""
Infineon DPS310 High accuracy pressure and temperature
"""
RAK12035: _TelemetrySensorType.ValueType # 37
"""
RAKWireless RAK12035 Soil Moisture Sensor Module
"""
MAX17261: _TelemetrySensorType.ValueType # 38
"""
MAX17261 lipo battery gauge
"""
PCT2075: _TelemetrySensorType.ValueType # 39
"""
PCT2075 Temperature Sensor
"""
ADS1X15: _TelemetrySensorType.ValueType # 40
"""
ADS1X15 ADC
"""
ADS1X15_ALT: _TelemetrySensorType.ValueType # 41
"""
ADS1X15 ADC_ALT
"""
SFA30: _TelemetrySensorType.ValueType # 42
"""
Sensirion SFA30 Formaldehyde sensor
"""
SEN5X: _TelemetrySensorType.ValueType # 43
"""
SEN5X PM SENSORS
"""
TSL2561: _TelemetrySensorType.ValueType # 44
"""
TSL2561 light sensor
"""
class TelemetrySensorType(_TelemetrySensorType, metaclass=_TelemetrySensorTypeEnumTypeWrapper):
"""
@@ -317,6 +353,42 @@ DFROBOT_RAIN: TelemetrySensorType.ValueType # 35
"""
DFRobot Gravity tipping bucket rain gauge
"""
DPS310: TelemetrySensorType.ValueType # 36
"""
Infineon DPS310 High accuracy pressure and temperature
"""
RAK12035: TelemetrySensorType.ValueType # 37
"""
RAKWireless RAK12035 Soil Moisture Sensor Module
"""
MAX17261: TelemetrySensorType.ValueType # 38
"""
MAX17261 lipo battery gauge
"""
PCT2075: TelemetrySensorType.ValueType # 39
"""
PCT2075 Temperature Sensor
"""
ADS1X15: TelemetrySensorType.ValueType # 40
"""
ADS1X15 ADC
"""
ADS1X15_ALT: TelemetrySensorType.ValueType # 41
"""
ADS1X15 ADC_ALT
"""
SFA30: TelemetrySensorType.ValueType # 42
"""
Sensirion SFA30 Formaldehyde sensor
"""
SEN5X: TelemetrySensorType.ValueType # 43
"""
SEN5X PM SENSORS
"""
TSL2561: TelemetrySensorType.ValueType # 44
"""
TSL2561 light sensor
"""
global___TelemetrySensorType = TelemetrySensorType
@typing.final
@@ -404,6 +476,8 @@ class EnvironmentMetrics(google.protobuf.message.Message):
RADIATION_FIELD_NUMBER: builtins.int
RAINFALL_1H_FIELD_NUMBER: builtins.int
RAINFALL_24H_FIELD_NUMBER: builtins.int
SOIL_MOISTURE_FIELD_NUMBER: builtins.int
SOIL_TEMPERATURE_FIELD_NUMBER: builtins.int
temperature: builtins.float
"""
Temperature measured
@@ -486,6 +560,14 @@ class EnvironmentMetrics(google.protobuf.message.Message):
"""
Rainfall in the last 24 hours in mm
"""
soil_moisture: builtins.int
"""
Soil moisture measured (% 1-100)
"""
soil_temperature: builtins.float
"""
Soil temperature measured (*C)
"""
def __init__(
self,
*,
@@ -509,9 +591,11 @@ class EnvironmentMetrics(google.protobuf.message.Message):
radiation: builtins.float | None = ...,
rainfall_1h: builtins.float | None = ...,
rainfall_24h: builtins.float | None = ...,
soil_moisture: builtins.int | None = ...,
soil_temperature: builtins.float | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_barometric_pressure", b"_barometric_pressure", "_current", b"_current", "_distance", b"_distance", "_gas_resistance", b"_gas_resistance", "_iaq", b"_iaq", "_ir_lux", b"_ir_lux", "_lux", b"_lux", "_radiation", b"_radiation", "_rainfall_1h", b"_rainfall_1h", "_rainfall_24h", b"_rainfall_24h", "_relative_humidity", b"_relative_humidity", "_temperature", b"_temperature", "_uv_lux", b"_uv_lux", "_voltage", b"_voltage", "_weight", b"_weight", "_white_lux", b"_white_lux", "_wind_direction", b"_wind_direction", "_wind_gust", b"_wind_gust", "_wind_lull", b"_wind_lull", "_wind_speed", b"_wind_speed", "barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "radiation", b"radiation", "rainfall_1h", b"rainfall_1h", "rainfall_24h", b"rainfall_24h", "relative_humidity", b"relative_humidity", "temperature", b"temperature", "uv_lux", b"uv_lux", "voltage", b"voltage", "weight", b"weight", "white_lux", b"white_lux", "wind_direction", b"wind_direction", "wind_gust", b"wind_gust", "wind_lull", b"wind_lull", "wind_speed", b"wind_speed"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_barometric_pressure", b"_barometric_pressure", "_current", b"_current", "_distance", b"_distance", "_gas_resistance", b"_gas_resistance", "_iaq", b"_iaq", "_ir_lux", b"_ir_lux", "_lux", b"_lux", "_radiation", b"_radiation", "_rainfall_1h", b"_rainfall_1h", "_rainfall_24h", b"_rainfall_24h", "_relative_humidity", b"_relative_humidity", "_temperature", b"_temperature", "_uv_lux", b"_uv_lux", "_voltage", b"_voltage", "_weight", b"_weight", "_white_lux", b"_white_lux", "_wind_direction", b"_wind_direction", "_wind_gust", b"_wind_gust", "_wind_lull", b"_wind_lull", "_wind_speed", b"_wind_speed", "barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "radiation", b"radiation", "rainfall_1h", b"rainfall_1h", "rainfall_24h", b"rainfall_24h", "relative_humidity", b"relative_humidity", "temperature", b"temperature", "uv_lux", b"uv_lux", "voltage", b"voltage", "weight", b"weight", "white_lux", b"white_lux", "wind_direction", b"wind_direction", "wind_gust", b"wind_gust", "wind_lull", b"wind_lull", "wind_speed", b"wind_speed"]) -> None: ...
def HasField(self, field_name: typing.Literal["_barometric_pressure", b"_barometric_pressure", "_current", b"_current", "_distance", b"_distance", "_gas_resistance", b"_gas_resistance", "_iaq", b"_iaq", "_ir_lux", b"_ir_lux", "_lux", b"_lux", "_radiation", b"_radiation", "_rainfall_1h", b"_rainfall_1h", "_rainfall_24h", b"_rainfall_24h", "_relative_humidity", b"_relative_humidity", "_soil_moisture", b"_soil_moisture", "_soil_temperature", b"_soil_temperature", "_temperature", b"_temperature", "_uv_lux", b"_uv_lux", "_voltage", b"_voltage", "_weight", b"_weight", "_white_lux", b"_white_lux", "_wind_direction", b"_wind_direction", "_wind_gust", b"_wind_gust", "_wind_lull", b"_wind_lull", "_wind_speed", b"_wind_speed", "barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "radiation", b"radiation", "rainfall_1h", b"rainfall_1h", "rainfall_24h", b"rainfall_24h", "relative_humidity", b"relative_humidity", "soil_moisture", b"soil_moisture", "soil_temperature", b"soil_temperature", "temperature", b"temperature", "uv_lux", b"uv_lux", "voltage", b"voltage", "weight", b"weight", "white_lux", b"white_lux", "wind_direction", b"wind_direction", "wind_gust", b"wind_gust", "wind_lull", b"wind_lull", "wind_speed", b"wind_speed"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_barometric_pressure", b"_barometric_pressure", "_current", b"_current", "_distance", b"_distance", "_gas_resistance", b"_gas_resistance", "_iaq", b"_iaq", "_ir_lux", b"_ir_lux", "_lux", b"_lux", "_radiation", b"_radiation", "_rainfall_1h", b"_rainfall_1h", "_rainfall_24h", b"_rainfall_24h", "_relative_humidity", b"_relative_humidity", "_soil_moisture", b"_soil_moisture", "_soil_temperature", b"_soil_temperature", "_temperature", b"_temperature", "_uv_lux", b"_uv_lux", "_voltage", b"_voltage", "_weight", b"_weight", "_white_lux", b"_white_lux", "_wind_direction", b"_wind_direction", "_wind_gust", b"_wind_gust", "_wind_lull", b"_wind_lull", "_wind_speed", b"_wind_speed", "barometric_pressure", b"barometric_pressure", "current", b"current", "distance", b"distance", "gas_resistance", b"gas_resistance", "iaq", b"iaq", "ir_lux", b"ir_lux", "lux", b"lux", "radiation", b"radiation", "rainfall_1h", b"rainfall_1h", "rainfall_24h", b"rainfall_24h", "relative_humidity", b"relative_humidity", "soil_moisture", b"soil_moisture", "soil_temperature", b"soil_temperature", "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
@@ -535,6 +619,10 @@ class EnvironmentMetrics(google.protobuf.message.Message):
@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["_soil_moisture", b"_soil_moisture"]) -> typing.Literal["soil_moisture"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_soil_temperature", b"_soil_temperature"]) -> typing.Literal["soil_temperature"] | 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: ...
@@ -569,6 +657,16 @@ class PowerMetrics(google.protobuf.message.Message):
CH2_CURRENT_FIELD_NUMBER: builtins.int
CH3_VOLTAGE_FIELD_NUMBER: builtins.int
CH3_CURRENT_FIELD_NUMBER: builtins.int
CH4_VOLTAGE_FIELD_NUMBER: builtins.int
CH4_CURRENT_FIELD_NUMBER: builtins.int
CH5_VOLTAGE_FIELD_NUMBER: builtins.int
CH5_CURRENT_FIELD_NUMBER: builtins.int
CH6_VOLTAGE_FIELD_NUMBER: builtins.int
CH6_CURRENT_FIELD_NUMBER: builtins.int
CH7_VOLTAGE_FIELD_NUMBER: builtins.int
CH7_CURRENT_FIELD_NUMBER: builtins.int
CH8_VOLTAGE_FIELD_NUMBER: builtins.int
CH8_CURRENT_FIELD_NUMBER: builtins.int
ch1_voltage: builtins.float
"""
Voltage (Ch1)
@@ -593,6 +691,46 @@ class PowerMetrics(google.protobuf.message.Message):
"""
Current (Ch3)
"""
ch4_voltage: builtins.float
"""
Voltage (Ch4)
"""
ch4_current: builtins.float
"""
Current (Ch4)
"""
ch5_voltage: builtins.float
"""
Voltage (Ch5)
"""
ch5_current: builtins.float
"""
Current (Ch5)
"""
ch6_voltage: builtins.float
"""
Voltage (Ch6)
"""
ch6_current: builtins.float
"""
Current (Ch6)
"""
ch7_voltage: builtins.float
"""
Voltage (Ch7)
"""
ch7_current: builtins.float
"""
Current (Ch7)
"""
ch8_voltage: builtins.float
"""
Voltage (Ch8)
"""
ch8_current: builtins.float
"""
Current (Ch8)
"""
def __init__(
self,
*,
@@ -602,9 +740,19 @@ class PowerMetrics(google.protobuf.message.Message):
ch2_current: builtins.float | None = ...,
ch3_voltage: builtins.float | None = ...,
ch3_current: builtins.float | None = ...,
ch4_voltage: builtins.float | None = ...,
ch4_current: builtins.float | None = ...,
ch5_voltage: builtins.float | None = ...,
ch5_current: builtins.float | None = ...,
ch6_voltage: builtins.float | None = ...,
ch6_current: builtins.float | None = ...,
ch7_voltage: builtins.float | None = ...,
ch7_current: builtins.float | None = ...,
ch8_voltage: builtins.float | None = ...,
ch8_current: builtins.float | None = ...,
) -> 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: ...
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", "_ch4_current", b"_ch4_current", "_ch4_voltage", b"_ch4_voltage", "_ch5_current", b"_ch5_current", "_ch5_voltage", b"_ch5_voltage", "_ch6_current", b"_ch6_current", "_ch6_voltage", b"_ch6_voltage", "_ch7_current", b"_ch7_current", "_ch7_voltage", b"_ch7_voltage", "_ch8_current", b"_ch8_current", "_ch8_voltage", b"_ch8_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", "ch4_current", b"ch4_current", "ch4_voltage", b"ch4_voltage", "ch5_current", b"ch5_current", "ch5_voltage", b"ch5_voltage", "ch6_current", b"ch6_current", "ch6_voltage", b"ch6_voltage", "ch7_current", b"ch7_current", "ch7_voltage", b"ch7_voltage", "ch8_current", b"ch8_current", "ch8_voltage", b"ch8_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", "_ch4_current", b"_ch4_current", "_ch4_voltage", b"_ch4_voltage", "_ch5_current", b"_ch5_current", "_ch5_voltage", b"_ch5_voltage", "_ch6_current", b"_ch6_current", "_ch6_voltage", b"_ch6_voltage", "_ch7_current", b"_ch7_current", "_ch7_voltage", b"_ch7_voltage", "_ch8_current", b"_ch8_current", "_ch8_voltage", b"_ch8_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", "ch4_current", b"ch4_current", "ch4_voltage", b"ch4_voltage", "ch5_current", b"ch5_current", "ch5_voltage", b"ch5_voltage", "ch6_current", b"ch6_current", "ch6_voltage", b"ch6_voltage", "ch7_current", b"ch7_current", "ch7_voltage", b"ch7_voltage", "ch8_current", b"ch8_current", "ch8_voltage", b"ch8_voltage"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch1_current", b"_ch1_current"]) -> typing.Literal["ch1_current"] | None: ...
@typing.overload
@@ -617,6 +765,26 @@ class PowerMetrics(google.protobuf.message.Message):
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: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch4_current", b"_ch4_current"]) -> typing.Literal["ch4_current"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch4_voltage", b"_ch4_voltage"]) -> typing.Literal["ch4_voltage"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch5_current", b"_ch5_current"]) -> typing.Literal["ch5_current"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch5_voltage", b"_ch5_voltage"]) -> typing.Literal["ch5_voltage"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch6_current", b"_ch6_current"]) -> typing.Literal["ch6_current"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch6_voltage", b"_ch6_voltage"]) -> typing.Literal["ch6_voltage"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch7_current", b"_ch7_current"]) -> typing.Literal["ch7_current"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch7_voltage", b"_ch7_voltage"]) -> typing.Literal["ch7_voltage"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch8_current", b"_ch8_current"]) -> typing.Literal["ch8_current"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_ch8_voltage", b"_ch8_voltage"]) -> typing.Literal["ch8_voltage"] | None: ...
global___PowerMetrics = PowerMetrics
@@ -641,57 +809,117 @@ class AirQualityMetrics(google.protobuf.message.Message):
PARTICLES_50UM_FIELD_NUMBER: builtins.int
PARTICLES_100UM_FIELD_NUMBER: builtins.int
CO2_FIELD_NUMBER: builtins.int
CO2_TEMPERATURE_FIELD_NUMBER: builtins.int
CO2_HUMIDITY_FIELD_NUMBER: builtins.int
FORM_FORMALDEHYDE_FIELD_NUMBER: builtins.int
FORM_HUMIDITY_FIELD_NUMBER: builtins.int
FORM_TEMPERATURE_FIELD_NUMBER: builtins.int
PM40_STANDARD_FIELD_NUMBER: builtins.int
PARTICLES_40UM_FIELD_NUMBER: builtins.int
PM_TEMPERATURE_FIELD_NUMBER: builtins.int
PM_HUMIDITY_FIELD_NUMBER: builtins.int
PM_VOC_IDX_FIELD_NUMBER: builtins.int
PM_NOX_IDX_FIELD_NUMBER: builtins.int
PARTICLES_TPS_FIELD_NUMBER: builtins.int
pm10_standard: builtins.int
"""
Concentration Units Standard PM1.0
Concentration Units Standard PM1.0 in ug/m3
"""
pm25_standard: builtins.int
"""
Concentration Units Standard PM2.5
Concentration Units Standard PM2.5 in ug/m3
"""
pm100_standard: builtins.int
"""
Concentration Units Standard PM10.0
Concentration Units Standard PM10.0 in ug/m3
"""
pm10_environmental: builtins.int
"""
Concentration Units Environmental PM1.0
Concentration Units Environmental PM1.0 in ug/m3
"""
pm25_environmental: builtins.int
"""
Concentration Units Environmental PM2.5
Concentration Units Environmental PM2.5 in ug/m3
"""
pm100_environmental: builtins.int
"""
Concentration Units Environmental PM10.0
Concentration Units Environmental PM10.0 in ug/m3
"""
particles_03um: builtins.int
"""
0.3um Particle Count
0.3um Particle Count in #/0.1l
"""
particles_05um: builtins.int
"""
0.5um Particle Count
0.5um Particle Count in #/0.1l
"""
particles_10um: builtins.int
"""
1.0um Particle Count
1.0um Particle Count in #/0.1l
"""
particles_25um: builtins.int
"""
2.5um Particle Count
2.5um Particle Count in #/0.1l
"""
particles_50um: builtins.int
"""
5.0um Particle Count
5.0um Particle Count in #/0.1l
"""
particles_100um: builtins.int
"""
10.0um Particle Count
10.0um Particle Count in #/0.1l
"""
co2: builtins.int
"""
10.0um Particle Count
CO2 concentration in ppm
"""
co2_temperature: builtins.float
"""
CO2 sensor temperature in degC
"""
co2_humidity: builtins.float
"""
CO2 sensor relative humidity in %
"""
form_formaldehyde: builtins.float
"""
Formaldehyde sensor formaldehyde concentration in ppb
"""
form_humidity: builtins.float
"""
Formaldehyde sensor relative humidity in %RH
"""
form_temperature: builtins.float
"""
Formaldehyde sensor temperature in degrees Celsius
"""
pm40_standard: builtins.int
"""
Concentration Units Standard PM4.0 in ug/m3
"""
particles_40um: builtins.int
"""
4.0um Particle Count in #/0.1l
"""
pm_temperature: builtins.float
"""
PM Sensor Temperature
"""
pm_humidity: builtins.float
"""
PM Sensor humidity
"""
pm_voc_idx: builtins.float
"""
PM Sensor VOC Index
"""
pm_nox_idx: builtins.float
"""
PM Sensor NOx Index
"""
particles_tps: builtins.float
"""
Typical Particle Size in um
"""
def __init__(
self,
@@ -709,12 +937,34 @@ class AirQualityMetrics(google.protobuf.message.Message):
particles_50um: builtins.int | None = ...,
particles_100um: builtins.int | None = ...,
co2: builtins.int | None = ...,
co2_temperature: builtins.float | None = ...,
co2_humidity: builtins.float | None = ...,
form_formaldehyde: builtins.float | None = ...,
form_humidity: builtins.float | None = ...,
form_temperature: builtins.float | None = ...,
pm40_standard: builtins.int | None = ...,
particles_40um: builtins.int | None = ...,
pm_temperature: builtins.float | None = ...,
pm_humidity: builtins.float | None = ...,
pm_voc_idx: builtins.float | None = ...,
pm_nox_idx: builtins.float | None = ...,
particles_tps: builtins.float | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_co2", b"_co2", "_particles_03um", b"_particles_03um", "_particles_05um", b"_particles_05um", "_particles_100um", b"_particles_100um", "_particles_10um", b"_particles_10um", "_particles_25um", b"_particles_25um", "_particles_50um", b"_particles_50um", "_pm100_environmental", b"_pm100_environmental", "_pm100_standard", b"_pm100_standard", "_pm10_environmental", b"_pm10_environmental", "_pm10_standard", b"_pm10_standard", "_pm25_environmental", b"_pm25_environmental", "_pm25_standard", b"_pm25_standard", "co2", b"co2", "particles_03um", b"particles_03um", "particles_05um", b"particles_05um", "particles_100um", b"particles_100um", "particles_10um", b"particles_10um", "particles_25um", b"particles_25um", "particles_50um", b"particles_50um", "pm100_environmental", b"pm100_environmental", "pm100_standard", b"pm100_standard", "pm10_environmental", b"pm10_environmental", "pm10_standard", b"pm10_standard", "pm25_environmental", b"pm25_environmental", "pm25_standard", b"pm25_standard"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_co2", b"_co2", "_particles_03um", b"_particles_03um", "_particles_05um", b"_particles_05um", "_particles_100um", b"_particles_100um", "_particles_10um", b"_particles_10um", "_particles_25um", b"_particles_25um", "_particles_50um", b"_particles_50um", "_pm100_environmental", b"_pm100_environmental", "_pm100_standard", b"_pm100_standard", "_pm10_environmental", b"_pm10_environmental", "_pm10_standard", b"_pm10_standard", "_pm25_environmental", b"_pm25_environmental", "_pm25_standard", b"_pm25_standard", "co2", b"co2", "particles_03um", b"particles_03um", "particles_05um", b"particles_05um", "particles_100um", b"particles_100um", "particles_10um", b"particles_10um", "particles_25um", b"particles_25um", "particles_50um", b"particles_50um", "pm100_environmental", b"pm100_environmental", "pm100_standard", b"pm100_standard", "pm10_environmental", b"pm10_environmental", "pm10_standard", b"pm10_standard", "pm25_environmental", b"pm25_environmental", "pm25_standard", b"pm25_standard"]) -> None: ...
def HasField(self, field_name: typing.Literal["_co2", b"_co2", "_co2_humidity", b"_co2_humidity", "_co2_temperature", b"_co2_temperature", "_form_formaldehyde", b"_form_formaldehyde", "_form_humidity", b"_form_humidity", "_form_temperature", b"_form_temperature", "_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_40um", b"_particles_40um", "_particles_50um", b"_particles_50um", "_particles_tps", b"_particles_tps", "_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", "_pm40_standard", b"_pm40_standard", "_pm_humidity", b"_pm_humidity", "_pm_nox_idx", b"_pm_nox_idx", "_pm_temperature", b"_pm_temperature", "_pm_voc_idx", b"_pm_voc_idx", "co2", b"co2", "co2_humidity", b"co2_humidity", "co2_temperature", b"co2_temperature", "form_formaldehyde", b"form_formaldehyde", "form_humidity", b"form_humidity", "form_temperature", b"form_temperature", "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_40um", b"particles_40um", "particles_50um", b"particles_50um", "particles_tps", b"particles_tps", "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", "pm40_standard", b"pm40_standard", "pm_humidity", b"pm_humidity", "pm_nox_idx", b"pm_nox_idx", "pm_temperature", b"pm_temperature", "pm_voc_idx", b"pm_voc_idx"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_co2", b"_co2", "_co2_humidity", b"_co2_humidity", "_co2_temperature", b"_co2_temperature", "_form_formaldehyde", b"_form_formaldehyde", "_form_humidity", b"_form_humidity", "_form_temperature", b"_form_temperature", "_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_40um", b"_particles_40um", "_particles_50um", b"_particles_50um", "_particles_tps", b"_particles_tps", "_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", "_pm40_standard", b"_pm40_standard", "_pm_humidity", b"_pm_humidity", "_pm_nox_idx", b"_pm_nox_idx", "_pm_temperature", b"_pm_temperature", "_pm_voc_idx", b"_pm_voc_idx", "co2", b"co2", "co2_humidity", b"co2_humidity", "co2_temperature", b"co2_temperature", "form_formaldehyde", b"form_formaldehyde", "form_humidity", b"form_humidity", "form_temperature", b"form_temperature", "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_40um", b"particles_40um", "particles_50um", b"particles_50um", "particles_tps", b"particles_tps", "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", "pm40_standard", b"pm40_standard", "pm_humidity", b"pm_humidity", "pm_nox_idx", b"pm_nox_idx", "pm_temperature", b"pm_temperature", "pm_voc_idx", b"pm_voc_idx"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_co2", b"_co2"]) -> typing.Literal["co2"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_co2_humidity", b"_co2_humidity"]) -> typing.Literal["co2_humidity"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_co2_temperature", b"_co2_temperature"]) -> typing.Literal["co2_temperature"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_form_formaldehyde", b"_form_formaldehyde"]) -> typing.Literal["form_formaldehyde"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_form_humidity", b"_form_humidity"]) -> typing.Literal["form_humidity"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_form_temperature", b"_form_temperature"]) -> typing.Literal["form_temperature"] | 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: ...
@@ -725,8 +975,12 @@ class AirQualityMetrics(google.protobuf.message.Message):
@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_40um", b"_particles_40um"]) -> typing.Literal["particles_40um"] | 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["_particles_tps", b"_particles_tps"]) -> typing.Literal["particles_tps"] | 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: ...
@@ -738,6 +992,16 @@ class AirQualityMetrics(google.protobuf.message.Message):
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: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_pm40_standard", b"_pm40_standard"]) -> typing.Literal["pm40_standard"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_pm_humidity", b"_pm_humidity"]) -> typing.Literal["pm_humidity"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_pm_nox_idx", b"_pm_nox_idx"]) -> typing.Literal["pm_nox_idx"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_pm_temperature", b"_pm_temperature"]) -> typing.Literal["pm_temperature"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_pm_voc_idx", b"_pm_voc_idx"]) -> typing.Literal["pm_voc_idx"] | None: ...
global___AirQualityMetrics = AirQualityMetrics
@@ -760,6 +1024,8 @@ class LocalStats(google.protobuf.message.Message):
NUM_RX_DUPE_FIELD_NUMBER: builtins.int
NUM_TX_RELAY_FIELD_NUMBER: builtins.int
NUM_TX_RELAY_CANCELED_FIELD_NUMBER: builtins.int
HEAP_TOTAL_BYTES_FIELD_NUMBER: builtins.int
HEAP_FREE_BYTES_FIELD_NUMBER: builtins.int
uptime_seconds: builtins.int
"""
How long the device has been running since the last reboot (in seconds)
@@ -806,6 +1072,14 @@ class LocalStats(google.protobuf.message.Message):
Number of times we canceled a packet to be relayed, because someone else did it before us.
This will always be zero for ROUTERs/REPEATERs. If this number is high, some other node(s) is/are relaying faster than you.
"""
heap_total_bytes: builtins.int
"""
Number of bytes used in the heap
"""
heap_free_bytes: builtins.int
"""
Number of bytes free in the heap
"""
def __init__(
self,
*,
@@ -820,8 +1094,10 @@ class LocalStats(google.protobuf.message.Message):
num_rx_dupe: builtins.int = ...,
num_tx_relay: builtins.int = ...,
num_tx_relay_canceled: builtins.int = ...,
heap_total_bytes: builtins.int = ...,
heap_free_bytes: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["air_util_tx", b"air_util_tx", "channel_utilization", b"channel_utilization", "num_online_nodes", b"num_online_nodes", "num_packets_rx", b"num_packets_rx", "num_packets_rx_bad", b"num_packets_rx_bad", "num_packets_tx", b"num_packets_tx", "num_rx_dupe", b"num_rx_dupe", "num_total_nodes", b"num_total_nodes", "num_tx_relay", b"num_tx_relay", "num_tx_relay_canceled", b"num_tx_relay_canceled", "uptime_seconds", b"uptime_seconds"]) -> None: ...
def ClearField(self, field_name: typing.Literal["air_util_tx", b"air_util_tx", "channel_utilization", b"channel_utilization", "heap_free_bytes", b"heap_free_bytes", "heap_total_bytes", b"heap_total_bytes", "num_online_nodes", b"num_online_nodes", "num_packets_rx", b"num_packets_rx", "num_packets_rx_bad", b"num_packets_rx_bad", "num_packets_tx", b"num_packets_tx", "num_rx_dupe", b"num_rx_dupe", "num_total_nodes", b"num_total_nodes", "num_tx_relay", b"num_tx_relay", "num_tx_relay_canceled", b"num_tx_relay_canceled", "uptime_seconds", b"uptime_seconds"]) -> None: ...
global___LocalStats = LocalStats
@@ -866,6 +1142,84 @@ class HealthMetrics(google.protobuf.message.Message):
global___HealthMetrics = HealthMetrics
@typing.final
class HostMetrics(google.protobuf.message.Message):
"""
Linux host metrics
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
UPTIME_SECONDS_FIELD_NUMBER: builtins.int
FREEMEM_BYTES_FIELD_NUMBER: builtins.int
DISKFREE1_BYTES_FIELD_NUMBER: builtins.int
DISKFREE2_BYTES_FIELD_NUMBER: builtins.int
DISKFREE3_BYTES_FIELD_NUMBER: builtins.int
LOAD1_FIELD_NUMBER: builtins.int
LOAD5_FIELD_NUMBER: builtins.int
LOAD15_FIELD_NUMBER: builtins.int
USER_STRING_FIELD_NUMBER: builtins.int
uptime_seconds: builtins.int
"""
Host system uptime
"""
freemem_bytes: builtins.int
"""
Host system free memory
"""
diskfree1_bytes: builtins.int
"""
Host system disk space free for /
"""
diskfree2_bytes: builtins.int
"""
Secondary system disk space free
"""
diskfree3_bytes: builtins.int
"""
Tertiary disk space free
"""
load1: builtins.int
"""
Host system one minute load in 1/100ths
"""
load5: builtins.int
"""
Host system five minute load in 1/100ths
"""
load15: builtins.int
"""
Host system fifteen minute load in 1/100ths
"""
user_string: builtins.str
"""
Optional User-provided string for arbitrary host system information
that doesn't make sense as a dedicated entry.
"""
def __init__(
self,
*,
uptime_seconds: builtins.int = ...,
freemem_bytes: builtins.int = ...,
diskfree1_bytes: builtins.int = ...,
diskfree2_bytes: builtins.int | None = ...,
diskfree3_bytes: builtins.int | None = ...,
load1: builtins.int = ...,
load5: builtins.int = ...,
load15: builtins.int = ...,
user_string: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["_diskfree2_bytes", b"_diskfree2_bytes", "_diskfree3_bytes", b"_diskfree3_bytes", "_user_string", b"_user_string", "diskfree2_bytes", b"diskfree2_bytes", "diskfree3_bytes", b"diskfree3_bytes", "user_string", b"user_string"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["_diskfree2_bytes", b"_diskfree2_bytes", "_diskfree3_bytes", b"_diskfree3_bytes", "_user_string", b"_user_string", "diskfree1_bytes", b"diskfree1_bytes", "diskfree2_bytes", b"diskfree2_bytes", "diskfree3_bytes", b"diskfree3_bytes", "freemem_bytes", b"freemem_bytes", "load1", b"load1", "load15", b"load15", "load5", b"load5", "uptime_seconds", b"uptime_seconds", "user_string", b"user_string"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_diskfree2_bytes", b"_diskfree2_bytes"]) -> typing.Literal["diskfree2_bytes"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_diskfree3_bytes", b"_diskfree3_bytes"]) -> typing.Literal["diskfree3_bytes"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing.Literal["_user_string", b"_user_string"]) -> typing.Literal["user_string"] | None: ...
global___HostMetrics = HostMetrics
@typing.final
class Telemetry(google.protobuf.message.Message):
"""
@@ -881,6 +1235,7 @@ class Telemetry(google.protobuf.message.Message):
POWER_METRICS_FIELD_NUMBER: builtins.int
LOCAL_STATS_FIELD_NUMBER: builtins.int
HEALTH_METRICS_FIELD_NUMBER: builtins.int
HOST_METRICS_FIELD_NUMBER: builtins.int
time: builtins.int
"""
Seconds since 1970 - or 0 for unknown/unset
@@ -921,6 +1276,12 @@ class Telemetry(google.protobuf.message.Message):
Health telemetry metrics
"""
@property
def host_metrics(self) -> global___HostMetrics:
"""
Linux host metrics
"""
def __init__(
self,
*,
@@ -931,10 +1292,11 @@ class Telemetry(google.protobuf.message.Message):
power_metrics: global___PowerMetrics | None = ...,
local_stats: global___LocalStats | None = ...,
health_metrics: global___HealthMetrics | None = ...,
host_metrics: global___HostMetrics | 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", "health_metrics", b"health_metrics", "local_stats", b"local_stats", "power_metrics", b"power_metrics", "variant", b"variant"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "health_metrics", b"health_metrics", "local_stats", b"local_stats", "power_metrics", b"power_metrics", "time", b"time", "variant", b"variant"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["variant", b"variant"]) -> typing.Literal["device_metrics", "environment_metrics", "air_quality_metrics", "power_metrics", "local_stats", "health_metrics"] | None: ...
def HasField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "health_metrics", b"health_metrics", "host_metrics", b"host_metrics", "local_stats", b"local_stats", "power_metrics", b"power_metrics", "variant", b"variant"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["air_quality_metrics", b"air_quality_metrics", "device_metrics", b"device_metrics", "environment_metrics", b"environment_metrics", "health_metrics", b"health_metrics", "host_metrics", b"host_metrics", "local_stats", b"local_stats", "power_metrics", b"power_metrics", "time", b"time", "variant", b"variant"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["variant", b"variant"]) -> typing.Literal["device_metrics", "environment_metrics", "air_quality_metrics", "power_metrics", "local_stats", "health_metrics", "host_metrics"] | None: ...
global___Telemetry = Telemetry

View File

@@ -66,6 +66,17 @@ class SerialInterface(StreamInterface):
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes
)
def __repr__(self):
rep = f"SerialInterface(devPath={self.devPath!r}"
if hasattr(self, 'debugOut') and self.debugOut is not None:
rep += f", debugOut={self.debugOut!r}"
if self.noProto:
rep += ", noProto=True"
if hasattr(self, 'noNodes') and self.noNodes:
rep += ", noNodes=True"
rep += ")"
return rep
def close(self) -> None:
"""Close a connection to the device"""
if self.stream: # Stream can be null if we were already closed

View File

@@ -207,6 +207,18 @@ nano_g1 = SupportedDevice(
usb_product_id_in_hex="55d4",
)
seeed_xiao_s3 = SupportedDevice(
name = "Seeed Xiao ESP32-S3",
version = "",
for_firmware="seeed-xiao-esp32s3",
baseport_on_linux="ttyACM",
baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="2886",
usb_product_id_in_hex="0059",
)
supported_devices = [
tbeam_v0_7,
tbeam_v1_1,
@@ -226,4 +238,5 @@ supported_devices = [
rak4631_19003,
rak11200,
nano_g1,
seeed_xiao_s3,
]

View File

@@ -1,9 +1,11 @@
"""TCPInterface class for interfacing with http endpoint
"""
# pylint: disable=R0917
import contextlib
import logging
import socket
from typing import Optional, cast
import time
from typing import Optional
from meshtastic.stream_interface import StreamInterface
@@ -35,52 +37,78 @@ class TCPInterface(StreamInterface):
self.socket: Optional[socket.socket] = None
if connectNow:
logging.debug(f"Connecting to {hostname}") # type: ignore[str-bytes-safe]
server_address: tuple[str, int] = (hostname, portNumber)
sock: Optional[socket.socket] = socket.create_connection(server_address)
self.socket = sock
self.myConnect()
else:
self.socket = None
StreamInterface.__init__(
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes
)
super().__init__(debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes)
def __repr__(self):
rep = f"TCPInterface({self.hostname!r}"
if self.debugOut is not None:
rep += f", debugOut={self.debugOut!r}"
if self.noProto:
rep += ", noProto=True"
if self.socket is None:
rep += ", connectNow=False"
if self.portNumber != DEFAULT_TCP_PORT:
rep += f", portNumber={self.portNumber!r}"
if self.noNodes:
rep += ", noNodes=True"
rep += ")"
return rep
def _socket_shutdown(self) -> None:
"""Shutdown the socket.
Note: Broke out this line so the exception could be unit tested.
"""
if self.socket: #mian: please check that this should be "if self.socket:"
cast(socket.socket, self.socket).shutdown(socket.SHUT_RDWR)
if self.socket is not None:
self.socket.shutdown(socket.SHUT_RDWR)
def myConnect(self) -> None:
"""Connect to socket"""
server_address: tuple[str, int] = (self.hostname, self.portNumber)
sock: Optional[socket.socket] = socket.create_connection(server_address)
self.socket = sock
logging.debug(f"Connecting to {self.hostname}") # type: ignore[str-bytes-safe]
server_address = (self.hostname, self.portNumber)
self.socket = socket.create_connection(server_address)
def close(self) -> None:
"""Close a connection to the device"""
logging.debug("Closing TCP stream")
StreamInterface.close(self)
super().close()
# Sometimes the socket read might be blocked in the reader thread.
# Therefore we force the shutdown by closing the socket here
self._wantExit: bool = True
if not self.socket is None:
try:
self._wantExit = True
if self.socket is not None:
with contextlib.suppress(Exception): # Ignore errors in shutdown, because we might have a race with the server
self._socket_shutdown()
except:
pass # Ignore errors in shutdown, because we might have a race with the server
self.socket.close()
self.socket = None
def _writeBytes(self, b: bytes) -> None:
"""Write an array of bytes to our stream and flush"""
if self.socket:
if self.socket is not None:
self.socket.send(b)
def _readBytes(self, length) -> Optional[bytes]:
"""Read an array of bytes from our stream"""
if self.socket:
return self.socket.recv(length)
else:
return None
if self.socket is not None:
data = self.socket.recv(length)
# empty byte indicates a disconnected socket,
# we need to handle it to avoid an infinite loop reading from null socket
if data == b'':
logging.debug("dead socket, re-connecting")
# cleanup and reconnect socket without breaking reader thread
with contextlib.suppress(Exception):
self._socket_shutdown()
self.socket.close()
self.socket = None
time.sleep(1)
self.myConnect()
self._startConfig()
return None
return data
# no socket, break reader thread
self._wantExit = True
return None

View File

@@ -6,7 +6,11 @@ import sys
import pytest
from meshtastic.analysis.__main__ import main
try:
# Depends upon matplotlib & other packages in poetry's analysis group, not installed by default
from meshtastic.analysis.__main__ import main
except ImportError:
pytest.skip("Can't import meshtastic.analysis", allow_module_level=True)
@pytest.mark.unit

View File

@@ -18,6 +18,7 @@ from meshtastic.__main__ import (
onNode,
onReceive,
tunnelMain,
set_missing_flags_false,
)
from meshtastic import mt_config
@@ -454,6 +455,37 @@ def test_main_set_owner_short_to_bob(capsys):
assert err == ""
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_is_unmessageable_to_true(capsys):
"""Test --set-is-unmessageable true"""
sys.argv = ["", "--set-is-unmessageable", "true"]
mt_config.args = sys.argv
iface = MagicMock(autospec=SerialInterface)
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE)
assert re.search(r"Setting device owner is_unmessageable to True", out, re.MULTILINE)
assert err == ""
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_is_unmessagable_to_true(capsys):
"""Test --set-is-unmessagable true"""
sys.argv = ["", "--set-is-unmessagable", "true"]
mt_config.args = sys.argv
iface = MagicMock(autospec=SerialInterface)
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE)
assert re.search(r"Setting device owner is_unmessageable to True", out, re.MULTILINE)
assert err == ""
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
@@ -494,6 +526,44 @@ def test_main_get_canned_messages(capsys, caplog, iface_with_nodes):
assert err == ""
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_ringtone(capsys):
"""Test --set-ringtone"""
sys.argv = ["", "--set-ringtone", "foo,bar"]
mt_config.args = sys.argv
iface = MagicMock(autospec=SerialInterface)
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE)
assert re.search(r"Setting ringtone to foo,bar", out, re.MULTILINE)
assert err == ""
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_get_ringtone(capsys, caplog, iface_with_nodes):
"""Test --get-ringtone"""
sys.argv = ["", "--get-ringtone"]
mt_config.args = sys.argv
iface = iface_with_nodes
iface.devPath = "bar"
mocked_node = MagicMock(autospec=Node)
mocked_node.get_ringtone.return_value = "foo,bar"
iface.localNode = mocked_node
with caplog.at_level(logging.DEBUG):
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r"Connected to radio", out, re.MULTILINE)
assert re.search(r"ringtone:foo,bar", out, re.MULTILINE)
assert err == ""
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
@@ -1724,6 +1794,8 @@ def test_main_export_config(capsys):
mo.getLongName.return_value = "foo"
mo.getShortName.return_value = "oof"
mo.localNode.getURL.return_value = "bar"
mo.getCannedMessage.return_value = "foo|bar"
mo.getRingtone.return_value = "24:d=32,o=5"
mo.getMyNodeInfo().get.return_value = {
"latitudeI": 1100000000,
"longitudeI": 1200000000,
@@ -1738,7 +1810,8 @@ position_broadcast_smart: true
fixed_position: true
position_flags: 35"""
export_config(mo)
out, err = capsys.readouterr()
out = export_config(mo)
err = ""
# ensure we do not output this line
assert not re.search(r"Connected to radio", out, re.MULTILINE)
@@ -1825,6 +1898,41 @@ position_flags: 35"""
# mo.assert_called()
@pytest.mark.unit
def test_set_missing_flags_false():
"""Test set_missing_flags_false() function"""
config = {
"bluetooth": {
"enabled": True
},
"lora": {
"txEnabled": True
}
}
false_defaults = {
("bluetooth", "enabled"),
("lora", "sx126xRxBoostedGain"),
("lora", "txEnabled"),
("lora", "usePreset"),
("position", "positionBroadcastSmartEnabled"),
("security", "serialEnabled"),
("mqtt", "encryptionEnabled"),
}
set_missing_flags_false(config, false_defaults)
# Preserved
assert config["bluetooth"]["enabled"] is True
assert config["lora"]["txEnabled"] is True
# Added
assert config["lora"]["usePreset"] is False
assert config["lora"]["sx126xRxBoostedGain"] is False
assert config["position"]["positionBroadcastSmartEnabled"] is False
assert config["security"]["serialEnabled"] is False
assert config["mqtt"]["encryptionEnabled"] is False
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_gpio_rd_no_gpio_channel(capsys):
@@ -2713,3 +2821,91 @@ def test_remove_ignored_node():
main()
mocked_node.removeIgnored.assert_called_once_with("!12345678")
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_owner_whitespace_only(capsys):
"""Test --set-owner with whitespace-only name"""
sys.argv = ["", "--set-owner", " "]
mt_config.args = sys.argv
with pytest.raises(SystemExit) as excinfo:
main()
out, _ = capsys.readouterr()
assert "ERROR: Long Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_owner_empty_string(capsys):
"""Test --set-owner with empty string"""
sys.argv = ["", "--set-owner", ""]
mt_config.args = sys.argv
with pytest.raises(SystemExit) as excinfo:
main()
out, _ = capsys.readouterr()
assert "ERROR: Long Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_owner_short_whitespace_only(capsys):
"""Test --set-owner-short with whitespace-only name"""
sys.argv = ["", "--set-owner-short", " "]
mt_config.args = sys.argv
with pytest.raises(SystemExit) as excinfo:
main()
out, _ = capsys.readouterr()
assert "ERROR: Short Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_owner_short_empty_string(capsys):
"""Test --set-owner-short with empty string"""
sys.argv = ["", "--set-owner-short", ""]
mt_config.args = sys.argv
with pytest.raises(SystemExit) as excinfo:
main()
out, _ = capsys.readouterr()
assert "ERROR: Short Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_ham_whitespace_only(capsys):
"""Test --set-ham with whitespace-only name"""
sys.argv = ["", "--set-ham", " "]
mt_config.args = sys.argv
with pytest.raises(SystemExit) as excinfo:
main()
out, _ = capsys.readouterr()
assert "ERROR: Ham radio callsign cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_main_set_ham_empty_string(capsys):
"""Test --set-ham with empty string"""
sys.argv = ["", "--set-ham", ""]
mt_config.args = sys.argv
with pytest.raises(SystemExit) as excinfo:
main()
out, _ = capsys.readouterr()
assert "ERROR: Ham radio callsign cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1

View File

@@ -11,8 +11,12 @@ from ..protobuf import mesh_pb2, config_pb2
from .. import BROADCAST_ADDR, LOCAL_ADDR
from ..mesh_interface import MeshInterface, _timeago
from ..node import Node
from ..slog import LogSet
from ..powermon import SimPowerSupply
try:
# Depends upon the powermon group, not installed by default
from ..slog import LogSet
from ..powermon import SimPowerSupply
except ImportError:
pytest.skip("Can't import LogSet or SimPowerSupply", allow_module_level=True)
# TODO
# from ..config import Config
@@ -521,6 +525,28 @@ def test_getMyNodeInfo():
myinfo = iface.getMyNodeInfo()
assert myinfo == anode
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_getCannedMessage():
"""Test MeshInterface.getCannedMessage()"""
iface = MeshInterface(noProto=True)
node = MagicMock()
node.get_canned_message.return_value = "Hi|Bye|Yes"
iface.localNode = node
result = iface.getCannedMessage()
assert result == "Hi|Bye|Yes"
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_getRingtone():
"""Test MeshInterface.getRingtone()"""
iface = MeshInterface(noProto=True)
node = MagicMock()
node.get_ringtone.return_value = "foo,bar"
iface.localNode = node
result = iface.getRingtone()
assert result == "foo,bar"
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
@@ -539,7 +565,6 @@ def test_generatePacketId(capsys):
assert err == ""
assert pytest_wrapped_e.type == MeshInterface.MeshInterfaceError
@pytest.mark.unit
@pytest.mark.usefixtures("reset_mt_config")
def test_fixupPosition_empty_pos():

View File

@@ -1254,8 +1254,7 @@ def test_requestChannels_non_localNode_starting_index(caplog):
# },
# 'id': 1692918436,
# 'hopLimit': 3,
# 'priority':
# 'RELIABLE',
# 'priority': 'RELIABLE',
# 'raw': 'fake',
# 'fromId': '!9388f81c',
# 'toId': '!9388f81c'
@@ -1480,6 +1479,77 @@ def test_remove_ignored(ignored):
iface.sendData.assert_called_once()
@pytest.mark.unit
def test_setOwner_whitespace_only_long_name(capsys):
"""Test setOwner with whitespace-only long name"""
iface = MagicMock(autospec=MeshInterface)
anode = Node(iface, 123, noProto=True)
with pytest.raises(SystemExit) as excinfo:
anode.setOwner(long_name=" ")
out, _ = capsys.readouterr()
assert "ERROR: Long Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
def test_setOwner_empty_long_name(capsys):
"""Test setOwner with empty long name"""
iface = MagicMock(autospec=MeshInterface)
anode = Node(iface, 123, noProto=True)
with pytest.raises(SystemExit) as excinfo:
anode.setOwner(long_name="")
out, _ = capsys.readouterr()
assert "ERROR: Long Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
def test_setOwner_whitespace_only_short_name(capsys):
"""Test setOwner with whitespace-only short name"""
iface = MagicMock(autospec=MeshInterface)
anode = Node(iface, 123, noProto=True)
with pytest.raises(SystemExit) as excinfo:
anode.setOwner(short_name=" ")
out, _ = capsys.readouterr()
assert "ERROR: Short Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
def test_setOwner_empty_short_name(capsys):
"""Test setOwner with empty short name"""
iface = MagicMock(autospec=MeshInterface)
anode = Node(iface, 123, noProto=True)
with pytest.raises(SystemExit) as excinfo:
anode.setOwner(short_name="")
out, _ = capsys.readouterr()
assert "ERROR: Short Name cannot be empty or contain only whitespace characters" in out
assert excinfo.value.code == 1
@pytest.mark.unit
def test_setOwner_valid_names(caplog):
"""Test setOwner with valid names"""
iface = MagicMock(autospec=MeshInterface)
anode = Node(iface, 123, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name="ValidName", short_name="VN")
# Should not raise any exceptions
# Note: When noProto=True, _sendAdmin is not called as the method returns early
assert re.search(r'p.set_owner.long_name:ValidName:', caplog.text, re.MULTILINE)
assert re.search(r'p.set_owner.short_name:VN:', caplog.text, re.MULTILINE)
# TODO
# @pytest.mark.unitslow
# def test_waitForConfig():

View File

@@ -9,7 +9,11 @@ import pytest
from meshtastic import mt_config
from ..tcp_interface import TCPInterface
from ..tunnel import Tunnel, onTunnelReceive
try:
# Depends upon pytap2, not installed by default
from ..tunnel import Tunnel, onTunnelReceive
except ImportError:
pytest.skip("Can't import Tunnel or onTunnelReceive", allow_module_level=True)
@pytest.mark.unit

View File

@@ -563,7 +563,7 @@ def test_active_ports_on_supported_devices_mac_duplicates_check(mock_platform, m
def test_message_to_json_shows_all():
"""Test that message_to_json prints fields that aren't included in data passed in"""
actual = json.loads(message_to_json(mesh_pb2.MyNodeInfo()))
expected = { "myNodeNum": 0, "rebootCount": 0, "minAppVersion": 0, "deviceId": "", "pioEnv": "" }
expected = { "myNodeNum": 0, "rebootCount": 0, "minAppVersion": 0, "deviceId": "", "pioEnv": "", 'firmwareEdition': 'VANILLA', 'nodedbCount': 0 }
assert actual == expected
@pytest.mark.unit

View File

@@ -198,9 +198,9 @@ class Timeout:
self.sleepInterval: float = 0.1
self.expireTimeout: int = maxSecs
def reset(self) -> None:
def reset(self, expireTimeout=None):
"""Restart the waitForSet timer"""
self.expireTime = time.time() + self.expireTimeout
self.expireTime = time.time() + (self.expireTimeout if expireTimeout is None else expireTimeout)
def waitForSet(self, target, attrs=()) -> bool:
"""Block until the specified attributes are set. Returns True if config has been received."""
@@ -225,8 +225,7 @@ class Timeout:
def waitForTraceRoute(self, waitFactor, acknowledgment, attr="receivedTraceRoute") -> bool:
"""Block until traceroute response is received. Returns True if traceroute response has been received."""
self.expireTimeout *= waitFactor
self.reset()
self.reset(self.expireTimeout * waitFactor)
while time.time() < self.expireTime:
if getattr(acknowledgment, attr, None):
acknowledgment.reset()

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "meshtastic"
version = "2.6.0"
version = "2.7.2"
description = "Python API & client shell for talking to Meshtastic devices"
authors = ["Meshtastic Developers <contact@meshtastic.org>"]
license = "GPL-3.0-only"