Compare commits

...

15 Commits

Author SHA1 Message Date
dependabot[bot]
47708ad946 Bump protobuf from 6.33.0 to 6.33.5
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 6.33.0 to 6.33.5.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Commits](https://github.com/protocolbuffers/protobuf/commits)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-version: 6.33.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-05 16:13:58 +00:00
Ian McEwen
cdf893e618 Merge pull request #893 from lexfrei/fix/ble-race-condition
fix(ble): resolve BLE connection hangs on macOS without --debug flag
2026-01-25 15:24:06 -07:00
Aleksei Sviridkin
9b9df9e585 fix(ble): resolve BLE hangs on macOS without --debug flag
This fixes two issues that caused BLE connections to hang on macOS
when not using the --debug flag:

1. Race condition in BLEClient event loop initialization
   - The event loop thread was started but asyncio operations were
     submitted before the loop was actually running
   - Added threading.Event synchronization to ensure the event loop
     is running before any operations are submitted
   - The ready signal is sent from within the loop via call_soon()
     to guarantee the loop is truly active

2. CoreBluetooth callback delivery on macOS
   - On macOS, CoreBluetooth requires occasional I/O operations for
     callbacks to be properly delivered to the main thread
   - Without --debug, no I/O was happening, causing callbacks to
     never be processed and operations to hang indefinitely
   - Added sys.stdout.flush() call before waiting for async results
     to trigger the necessary I/O

The --debug flag masked these issues because:
- Debug logging introduces timing delays that let the event loop start
- Logger I/O triggers the necessary callback delivery mechanism

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-01-25 03:06:58 +03:00
github-actions
b26d80f186 bump version to 2.7.7 2026-01-24 16:34:15 +00:00
Ian McEwen
da559f0e37 protobufs: v2.7.18 2026-01-24 09:31:04 -07:00
Ian McEwen
a73f432f42 Merge pull request #888 from dandrzejewski/node-favorites
Show favorite nodes in --nodes
2026-01-09 13:09:31 -07:00
David Andrzejewski
c3c5ce64dd Copilot had a few suggestions on code review, implemented them. 2026-01-08 19:08:18 -05:00
David Andrzejewski
683dd23d63 Fix a few pylint things. 2026-01-08 18:53:55 -05:00
David Andrzejewski
57d43b84e4 Merge branch 'master' into node-favorites 2026-01-08 18:40:43 -05:00
David Andrzejewski
4f6d183ed1 Show favorite nodes in --nodes 2026-01-08 18:13:03 -05:00
github-actions
9a72e36ca6 bump version to 2.7.6 2026-01-05 02:25:14 +00:00
Ian McEwen
4d54ee7431 protobufs: v2.7.17 2026-01-04 19:21:54 -07:00
Ian McEwen
5cc0dae394 protobufs: v2.7.15 2025-11-20 14:30:39 -07:00
Ian McEwen
1a50377d34 Merge pull request #865 from ianmcorvidae/device-metadata-details
Add a bunch more detail to --device-metadata output, from fields we weren't formerly using in the output.
2025-11-20 14:29:20 -07:00
Ian McEwen
2a44be9269 Add a bunch more detail to --device-metadata output, from fields we weren't formerly using in the output. 2025-11-20 11:42:57 -07:00
25 changed files with 922 additions and 228 deletions

View File

@@ -4,9 +4,10 @@ import asyncio
import atexit
import logging
import struct
import sys
import time
import io
from threading import Thread
from threading import Thread, Event
from typing import List, Optional
import google.protobuf
@@ -258,11 +259,13 @@ class BLEClient:
"""Client for managing connection to a BLE device"""
def __init__(self, address=None, **kwargs) -> None:
self._loop_ready = Event()
self._eventLoop = asyncio.new_event_loop()
self._eventThread = Thread(
target=self._run_event_loop, name="BLEClient", daemon=True
)
self._eventThread.start()
self._loop_ready.wait() # Wait for event loop to be running
if not address:
logger.debug("No address provided - only discover method will work.")
@@ -306,13 +309,28 @@ class BLEClient:
self.close()
def async_await(self, coro, timeout=None): # pylint: disable=C0116
return self.async_run(coro).result(timeout)
"""Wait for async operation to complete.
On macOS, CoreBluetooth requires occasional I/O operations for
callbacks to be properly delivered. The debug logging provides this
I/O when enabled, allowing the system to process pending callbacks.
"""
logger.debug(f"async_await: waiting for {coro}")
future = self.async_run(coro)
# On macOS without debug logging, callbacks may not be delivered
# unless we trigger some I/O. This is a known quirk of CoreBluetooth.
sys.stdout.flush()
result = future.result(timeout)
logger.debug("async_await: complete")
return result
def async_run(self, coro): # pylint: disable=C0116
return asyncio.run_coroutine_threadsafe(coro, self._eventLoop)
def _run_event_loop(self):
try:
# Signal ready from WITHIN the loop to guarantee it's actually running
self._eventLoop.call_soon(self._loop_ready.set)
self._eventLoop.run_forever()
finally:
self._eventLoop.close()

View File

@@ -253,6 +253,7 @@ class MeshInterface: # pylint: disable=R0902
"channel": "Channel",
"lastHeard": "LastHeard",
"since": "Since",
"isFavorite": "Fav",
}
@@ -300,7 +301,7 @@ class MeshInterface: # pylint: disable=R0902
showFields = ["N", "user.longName", "user.id", "user.shortName", "user.hwModel", "user.publicKey",
"user.role", "position.latitude", "position.longitude", "position.altitude",
"deviceMetrics.batteryLevel", "deviceMetrics.channelUtilization",
"deviceMetrics.airUtilTx", "snr", "hopsAway", "channel", "lastHeard", "since"]
"deviceMetrics.airUtilTx", "snr", "hopsAway", "channel", "isFavorite", "lastHeard", "since"]
else:
# Always at least include the row number.
showFields.insert(0, "N")
@@ -342,6 +343,8 @@ class MeshInterface: # pylint: disable=R0902
formatted_value = "Powered"
else:
formatted_value = formatFloat(raw_value, 0, "%")
elif field == "isFavorite":
formatted_value = "*" if raw_value else ""
elif field == "lastHeard":
formatted_value = getLH(raw_value)
elif field == "position.latitude":

View File

@@ -7,7 +7,7 @@ import time
from typing import Optional, Union, List
from meshtastic.protobuf import admin_pb2, apponly_pb2, channel_pb2, localonly_pb2, mesh_pb2, portnums_pb2
from meshtastic.protobuf import admin_pb2, apponly_pb2, channel_pb2, config_pb2, localonly_pb2, mesh_pb2, portnums_pb2
from meshtastic.util import (
Timeout,
camel_to_snake,
@@ -18,6 +18,7 @@ from meshtastic.util import (
message_to_json,
generate_channel_hash,
to_node_num,
flags_to_list,
)
logger = logging.getLogger(__name__)
@@ -54,6 +55,16 @@ class Node:
r += ")"
return r
@staticmethod
def position_flags_list(position_flags: int) -> List[str]:
"Return a list of position flags from the given flags integer"
return flags_to_list(config_pb2.Config.PositionConfig.PositionFlags, position_flags)
@staticmethod
def excluded_modules_list(excluded_modules: int) -> List[str]:
"Return a list of excluded modules from the given flags integer"
return flags_to_list(mesh_pb2.ExcludedModules, excluded_modules)
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)
@@ -902,6 +913,18 @@ class Node:
logger.debug(f"Received metadata {stripnl(c)}")
print(f"\nfirmware_version: {c.firmware_version}")
print(f"device_state_version: {c.device_state_version}")
if c.role in config_pb2.Config.DeviceConfig.Role.values():
print(f"role: {config_pb2.Config.DeviceConfig.Role.Name(c.role)}")
else:
print(f"role: {c.role}")
print(f"position_flags: {self.position_flags_list(c.position_flags)}")
if c.hw_model in mesh_pb2.HardwareModel.values():
print(f"hw_model: {mesh_pb2.HardwareModel.Name(c.hw_model)}")
else:
print(f"hw_model: {c.hw_model}")
print(f"hasPKC: {c.hasPKC}")
if c.excluded_modules > 0:
print(f"excluded_modules: {self.excluded_modules_list(c.excluded_modules)}")
def onResponseRequestChannel(self, p):
"""Handle the response packet for requesting a channel _requestChannel()"""

View File

File diff suppressed because one or more lines are too long

View File

@@ -25,6 +25,44 @@ else:
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class _OTAMode:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _OTAModeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_OTAMode.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
NO_REBOOT_OTA: _OTAMode.ValueType # 0
"""
Do not reboot into OTA mode
"""
OTA_BLE: _OTAMode.ValueType # 1
"""
Reboot into OTA mode for BLE firmware update
"""
OTA_WIFI: _OTAMode.ValueType # 2
"""
Reboot into OTA mode for WiFi firmware update
"""
class OTAMode(_OTAMode, metaclass=_OTAModeEnumTypeWrapper):
"""
Firmware update mode for OTA updates
"""
NO_REBOOT_OTA: OTAMode.ValueType # 0
"""
Do not reboot into OTA mode
"""
OTA_BLE: OTAMode.ValueType # 1
"""
Reboot into OTA mode for BLE firmware update
"""
OTA_WIFI: OTAMode.ValueType # 2
"""
Reboot into OTA mode for WiFi firmware update
"""
global___OTAMode = OTAMode
@typing.final
class AdminMessage(google.protobuf.message.Message):
"""
@@ -186,6 +224,10 @@ class AdminMessage(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
STATUSMESSAGE_CONFIG: AdminMessage._ModuleConfigType.ValueType # 13
"""
TODO: REPLACE
"""
class ModuleConfigType(_ModuleConfigType, metaclass=_ModuleConfigTypeEnumTypeWrapper):
"""
@@ -244,6 +286,10 @@ class AdminMessage(google.protobuf.message.Message):
"""
TODO: REPLACE
"""
STATUSMESSAGE_CONFIG: AdminMessage.ModuleConfigType.ValueType # 13
"""
TODO: REPLACE
"""
class _BackupLocation:
ValueType = typing.NewType("ValueType", builtins.int)
@@ -308,6 +354,34 @@ class AdminMessage(google.protobuf.message.Message):
) -> 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: ...
@typing.final
class OTAEvent(google.protobuf.message.Message):
"""
User is requesting an over the air update.
Node will reboot into the OTA loader
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
REBOOT_OTA_MODE_FIELD_NUMBER: builtins.int
OTA_HASH_FIELD_NUMBER: builtins.int
reboot_ota_mode: global___OTAMode.ValueType
"""
Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only for now)
"""
ota_hash: builtins.bytes
"""
A 32 byte hash of the OTA firmware.
Used to verify the integrity of the firmware before applying an update.
"""
def __init__(
self,
*,
reboot_ota_mode: global___OTAMode.ValueType = ...,
ota_hash: builtins.bytes = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["ota_hash", b"ota_hash", "reboot_ota_mode", b"reboot_ota_mode"]) -> None: ...
SESSION_PASSKEY_FIELD_NUMBER: builtins.int
GET_CHANNEL_REQUEST_FIELD_NUMBER: builtins.int
GET_CHANNEL_RESPONSE_FIELD_NUMBER: builtins.int
@@ -352,6 +426,7 @@ class AdminMessage(google.protobuf.message.Message):
STORE_UI_CONFIG_FIELD_NUMBER: builtins.int
SET_IGNORED_NODE_FIELD_NUMBER: builtins.int
REMOVE_IGNORED_NODE_FIELD_NUMBER: builtins.int
TOGGLE_MUTED_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
@@ -363,6 +438,7 @@ class AdminMessage(google.protobuf.message.Message):
SHUTDOWN_SECONDS_FIELD_NUMBER: builtins.int
FACTORY_RESET_CONFIG_FIELD_NUMBER: builtins.int
NODEDB_RESET_FIELD_NUMBER: builtins.int
OTA_REQUEST_FIELD_NUMBER: builtins.int
session_passkey: builtins.bytes
"""
The node generates this key and sends it with any get_x_response packets.
@@ -480,6 +556,10 @@ class AdminMessage(google.protobuf.message.Message):
"""
Set specified node-num to be un-ignored on the NodeDB on the device
"""
toggle_muted_node: builtins.int
"""
Set specified node-num to be muted
"""
begin_edit_settings: builtins.bool
"""
Begins an edit transaction for config, module config, owner, and channel settings changes
@@ -497,6 +577,7 @@ class AdminMessage(google.protobuf.message.Message):
"""
Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth.
Deprecated in favor of reboot_ota_mode in 2.7.17
"""
exit_simulator: builtins.bool
"""
@@ -515,9 +596,10 @@ class AdminMessage(google.protobuf.message.Message):
"""
Tell the node to factory reset config; all device state and configuration will be returned to factory defaults; BLE bonds will be preserved.
"""
nodedb_reset: builtins.int
nodedb_reset: builtins.bool
"""
Tell the node to reset the nodedb.
When true, favorites are preserved through reset.
"""
@property
def get_channel_response(self) -> meshtastic.protobuf.channel_pb2.Channel:
@@ -632,6 +714,12 @@ class AdminMessage(google.protobuf.message.Message):
Initiate or respond to a key verification request
"""
@property
def ota_request(self) -> global___AdminMessage.OTAEvent:
"""
Tell the node to reset into the OTA Loader
"""
def __init__(
self,
*,
@@ -679,6 +767,7 @@ class AdminMessage(google.protobuf.message.Message):
store_ui_config: meshtastic.protobuf.device_ui_pb2.DeviceUIConfig | None = ...,
set_ignored_node: builtins.int = ...,
remove_ignored_node: builtins.int = ...,
toggle_muted_node: builtins.int = ...,
begin_edit_settings: builtins.bool = ...,
commit_edit_settings: builtins.bool = ...,
add_contact: global___SharedContact | None = ...,
@@ -689,11 +778,12 @@ class AdminMessage(google.protobuf.message.Message):
reboot_seconds: builtins.int = ...,
shutdown_seconds: builtins.int = ...,
factory_reset_config: builtins.int = ...,
nodedb_reset: builtins.int = ...,
nodedb_reset: builtins.bool = ...,
ota_request: global___AdminMessage.OTAEvent | None = ...,
) -> 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: ...
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", "ota_request", b"ota_request", "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", "toggle_muted_node", b"toggle_muted_node"]) -> 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", "ota_request", b"ota_request", "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", "toggle_muted_node", b"toggle_muted_node"]) -> 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", "toggle_muted_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", "ota_request"] | None: ...
global___AdminMessage = AdminMessage

View File

@@ -1,7 +1,7 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
trunk-ignore(buf-lint/PACKAGE_DIRECTORY_MATCH)"""
import builtins
import google.protobuf.descriptor

View File

@@ -1,7 +1,7 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
trunk-ignore(buf-lint/PACKAGE_DIRECTORY_MATCH)"""
import builtins
import google.protobuf.descriptor

View File

File diff suppressed because one or more lines are too long

View File

@@ -119,7 +119,7 @@ class Config(google.protobuf.message.Message):
"""
CLIENT_BASE: Config.DeviceConfig._Role.ValueType # 12
"""
Description: Treats packets from or to favorited nodes as ROUTER, and all other packets as CLIENT.
Description: Treats packets from or to favorited nodes as ROUTER_LATE, and all other packets as CLIENT.
Technical Details: Used for stronger attic/roof nodes to distribute messages more widely
from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes
where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node.
@@ -211,7 +211,7 @@ class Config(google.protobuf.message.Message):
"""
CLIENT_BASE: Config.DeviceConfig.Role.ValueType # 12
"""
Description: Treats packets from or to favorited nodes as ROUTER, and all other packets as CLIENT.
Description: Treats packets from or to favorited nodes as ROUTER_LATE, and all other packets as CLIENT.
Technical Details: Used for stronger attic/roof nodes to distribute messages more widely
from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes
where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node.
@@ -1487,6 +1487,7 @@ class Config(google.protobuf.message.Message):
LONG_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 1
"""
Long Range - Slow
Deprecated in 2.7: Unpopular slow preset.
"""
VERY_LONG_SLOW: Config.LoRaConfig._ModemPreset.ValueType # 2
"""
@@ -1519,6 +1520,11 @@ class Config(google.protobuf.message.Message):
This is the fastest preset and the only one with 500kHz bandwidth.
It is not legal to use in all regions due to this wider bandwidth.
"""
LONG_TURBO: Config.LoRaConfig._ModemPreset.ValueType # 9
"""
Long Range - Turbo
This preset performs similarly to LongFast, but with 500Khz bandwidth.
"""
class ModemPreset(_ModemPreset, metaclass=_ModemPresetEnumTypeWrapper):
"""
@@ -1533,6 +1539,7 @@ class Config(google.protobuf.message.Message):
LONG_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 1
"""
Long Range - Slow
Deprecated in 2.7: Unpopular slow preset.
"""
VERY_LONG_SLOW: Config.LoRaConfig.ModemPreset.ValueType # 2
"""
@@ -1565,6 +1572,11 @@ class Config(google.protobuf.message.Message):
This is the fastest preset and the only one with 500kHz bandwidth.
It is not legal to use in all regions due to this wider bandwidth.
"""
LONG_TURBO: Config.LoRaConfig.ModemPreset.ValueType # 9
"""
Long Range - Turbo
This preset performs similarly to LongFast, but with 500Khz bandwidth.
"""
USE_PRESET_FIELD_NUMBER: builtins.int
MODEM_PRESET_FIELD_NUMBER: builtins.int

View File

@@ -197,6 +197,7 @@ class NodeInfoLite(google.protobuf.message.Message):
"""
Bitfield for storing booleans.
LSB 0 is_key_manually_verified
LSB 1 is_muted
"""
@property
def user(self) -> global___UserLite:

View File

@@ -15,7 +15,7 @@ from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config
from meshtastic.protobuf import module_config_pb2 as meshtastic_dot_protobuf_dot_module__config__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/localonly.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xfa\x03\n\x0bLocalConfig\x12\x38\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfig\x12<\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfig\x12\x36\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfig\x12:\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfig\x12:\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfig\x12\x34\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfig\x12>\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\x12<\n\x08security\x18\t \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfig\"\xf0\x07\n\x11LocalModuleConfig\x12:\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfig\x12>\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfig\x12[\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfig\x12K\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfig\x12\x45\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfig\x12\x44\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfig\x12M\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfig\x12<\n\x05\x61udio\x18\t \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfig\x12O\n\x0fremote_hardware\x18\n \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfig\x12K\n\rneighbor_info\x18\x0b \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfig\x12Q\n\x10\x61mbient_lighting\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfig\x12Q\n\x10\x64\x65tection_sensor\x18\r \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfig\x12\x46\n\npaxcounter\x18\x0e \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBe\n\x14org.meshtastic.protoB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/localonly.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/config.proto\x1a\'meshtastic/protobuf/module_config.proto\"\xfa\x03\n\x0bLocalConfig\x12\x38\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32(.meshtastic.protobuf.Config.DeviceConfig\x12<\n\x08position\x18\x02 \x01(\x0b\x32*.meshtastic.protobuf.Config.PositionConfig\x12\x36\n\x05power\x18\x03 \x01(\x0b\x32\'.meshtastic.protobuf.Config.PowerConfig\x12:\n\x07network\x18\x04 \x01(\x0b\x32).meshtastic.protobuf.Config.NetworkConfig\x12:\n\x07\x64isplay\x18\x05 \x01(\x0b\x32).meshtastic.protobuf.Config.DisplayConfig\x12\x34\n\x04lora\x18\x06 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfig\x12>\n\tbluetooth\x18\x07 \x01(\x0b\x32+.meshtastic.protobuf.Config.BluetoothConfig\x12\x0f\n\x07version\x18\x08 \x01(\r\x12<\n\x08security\x18\t \x01(\x0b\x32*.meshtastic.protobuf.Config.SecurityConfig\"\xbe\x08\n\x11LocalModuleConfig\x12:\n\x04mqtt\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.ModuleConfig.MQTTConfig\x12>\n\x06serial\x18\x02 \x01(\x0b\x32..meshtastic.protobuf.ModuleConfig.SerialConfig\x12[\n\x15\x65xternal_notification\x18\x03 \x01(\x0b\x32<.meshtastic.protobuf.ModuleConfig.ExternalNotificationConfig\x12K\n\rstore_forward\x18\x04 \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.StoreForwardConfig\x12\x45\n\nrange_test\x18\x05 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.RangeTestConfig\x12\x44\n\ttelemetry\x18\x06 \x01(\x0b\x32\x31.meshtastic.protobuf.ModuleConfig.TelemetryConfig\x12M\n\x0e\x63\x61nned_message\x18\x07 \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.CannedMessageConfig\x12<\n\x05\x61udio\x18\t \x01(\x0b\x32-.meshtastic.protobuf.ModuleConfig.AudioConfig\x12O\n\x0fremote_hardware\x18\n \x01(\x0b\x32\x36.meshtastic.protobuf.ModuleConfig.RemoteHardwareConfig\x12K\n\rneighbor_info\x18\x0b \x01(\x0b\x32\x34.meshtastic.protobuf.ModuleConfig.NeighborInfoConfig\x12Q\n\x10\x61mbient_lighting\x18\x0c \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.AmbientLightingConfig\x12Q\n\x10\x64\x65tection_sensor\x18\r \x01(\x0b\x32\x37.meshtastic.protobuf.ModuleConfig.DetectionSensorConfig\x12\x46\n\npaxcounter\x18\x0e \x01(\x0b\x32\x32.meshtastic.protobuf.ModuleConfig.PaxcounterConfig\x12L\n\rstatusmessage\x18\x0f \x01(\x0b\x32\x35.meshtastic.protobuf.ModuleConfig.StatusMessageConfig\x12\x0f\n\x07version\x18\x08 \x01(\rBe\n\x14org.meshtastic.protoB\x0fLocalOnlyProtosZ\"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['_LOCALCONFIG']._serialized_start=136
_globals['_LOCALCONFIG']._serialized_end=642
_globals['_LOCALMODULECONFIG']._serialized_start=645
_globals['_LOCALMODULECONFIG']._serialized_end=1653
_globals['_LOCALMODULECONFIG']._serialized_end=1731
# @@protoc_insertion_point(module_scope)

View File

@@ -119,6 +119,7 @@ class LocalModuleConfig(google.protobuf.message.Message):
AMBIENT_LIGHTING_FIELD_NUMBER: builtins.int
DETECTION_SENSOR_FIELD_NUMBER: builtins.int
PAXCOUNTER_FIELD_NUMBER: builtins.int
STATUSMESSAGE_FIELD_NUMBER: builtins.int
VERSION_FIELD_NUMBER: builtins.int
version: builtins.int
"""
@@ -204,6 +205,12 @@ class LocalModuleConfig(google.protobuf.message.Message):
Paxcounter Config
"""
@property
def statusmessage(self) -> meshtastic.protobuf.module_config_pb2.ModuleConfig.StatusMessageConfig:
"""
StatusMessage Config
"""
def __init__(
self,
*,
@@ -220,9 +227,10 @@ class LocalModuleConfig(google.protobuf.message.Message):
ambient_lighting: meshtastic.protobuf.module_config_pb2.ModuleConfig.AmbientLightingConfig | None = ...,
detection_sensor: meshtastic.protobuf.module_config_pb2.ModuleConfig.DetectionSensorConfig | None = ...,
paxcounter: meshtastic.protobuf.module_config_pb2.ModuleConfig.PaxcounterConfig | None = ...,
statusmessage: meshtastic.protobuf.module_config_pb2.ModuleConfig.StatusMessageConfig | None = ...,
version: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "store_forward", b"store_forward", "telemetry", b"telemetry", "version", b"version"]) -> None: ...
def HasField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "statusmessage", b"statusmessage", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "statusmessage", b"statusmessage", "store_forward", b"store_forward", "telemetry", b"telemetry", "version", b"version"]) -> None: ...
global___LocalModuleConfig = LocalModuleConfig

View File

File diff suppressed because one or more lines are too long

View File

@@ -168,9 +168,9 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
Less common/prototype boards listed here (needs one more byte over the air)
---------------------------------------------------------------------------
"""
NRF52840DK: _HardwareModel.ValueType # 33
T_ECHO_PLUS: _HardwareModel.ValueType # 33
"""
TODO: REPLACE
T-Echo Plus device from LilyGo
"""
PPR: _HardwareModel.ValueType # 34
"""
@@ -421,9 +421,9 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
"""
Heltec HRI-3621 industrial probe
"""
RESERVED_FRIED_CHICKEN: _HardwareModel.ValueType # 93
MUZI_BASE: _HardwareModel.ValueType # 93
"""
Reserved Fried Chicken ID for future use
Muzi Works Muzi-Base device
"""
HELTEC_MESH_POCKET: _HardwareModel.ValueType # 94
"""
@@ -523,6 +523,30 @@ class _HardwareModelEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._
"""
RAK3401
"""
RAK6421: _HardwareModel.ValueType # 118
"""
RAK6421 Hat+
"""
THINKNODE_M4: _HardwareModel.ValueType # 119
"""
Elecrow ThinkNode M4
"""
THINKNODE_M6: _HardwareModel.ValueType # 120
"""
Elecrow ThinkNode M6
"""
MESHSTICK_1262: _HardwareModel.ValueType # 121
"""
Elecrow Meshstick 1262
"""
TBEAM_1_WATT: _HardwareModel.ValueType # 122
"""
LilyGo T-Beam 1W
"""
T5_S3_EPAPER_PRO: _HardwareModel.ValueType # 123
"""
LilyGo T5 S3 ePaper Pro (V1 and V2)
"""
PRIVATE_HW: _HardwareModel.ValueType # 255
"""
------------------------------------------------------------------------------------------------------------------------------------------
@@ -674,9 +698,9 @@ LORA_RELAY_V1: HardwareModel.ValueType # 32
Less common/prototype boards listed here (needs one more byte over the air)
---------------------------------------------------------------------------
"""
NRF52840DK: HardwareModel.ValueType # 33
T_ECHO_PLUS: HardwareModel.ValueType # 33
"""
TODO: REPLACE
T-Echo Plus device from LilyGo
"""
PPR: HardwareModel.ValueType # 34
"""
@@ -927,9 +951,9 @@ HELTEC_SENSOR_HUB: HardwareModel.ValueType # 92
"""
Heltec HRI-3621 industrial probe
"""
RESERVED_FRIED_CHICKEN: HardwareModel.ValueType # 93
MUZI_BASE: HardwareModel.ValueType # 93
"""
Reserved Fried Chicken ID for future use
Muzi Works Muzi-Base device
"""
HELTEC_MESH_POCKET: HardwareModel.ValueType # 94
"""
@@ -1029,6 +1053,30 @@ RAK3401: HardwareModel.ValueType # 117
"""
RAK3401
"""
RAK6421: HardwareModel.ValueType # 118
"""
RAK6421 Hat+
"""
THINKNODE_M4: HardwareModel.ValueType # 119
"""
Elecrow ThinkNode M4
"""
THINKNODE_M6: HardwareModel.ValueType # 120
"""
Elecrow ThinkNode M6
"""
MESHSTICK_1262: HardwareModel.ValueType # 121
"""
Elecrow Meshstick 1262
"""
TBEAM_1_WATT: HardwareModel.ValueType # 122
"""
LilyGo T-Beam 1W
"""
T5_S3_EPAPER_PRO: HardwareModel.ValueType # 123
"""
LilyGo T5 S3 ePaper Pro (V1 and V2)
"""
PRIVATE_HW: HardwareModel.ValueType # 255
"""
------------------------------------------------------------------------------------------------------------------------------------------
@@ -1948,6 +1996,11 @@ class Routing(google.protobuf.message.Message):
Airtime fairness rate limit exceeded for a packet
This typically enforced per portnum and is used to prevent a single node from monopolizing airtime
"""
PKI_SEND_FAIL_PUBLIC_KEY: Routing._Error.ValueType # 39
"""
PKI encryption failed, due to no public key for the remote node
This is different from PKI_UNKNOWN_PUBKEY which indicates a failure upon receiving a packet
"""
class Error(_Error, metaclass=_ErrorEnumTypeWrapper):
"""
@@ -2026,6 +2079,11 @@ class Routing(google.protobuf.message.Message):
Airtime fairness rate limit exceeded for a packet
This typically enforced per portnum and is used to prevent a single node from monopolizing airtime
"""
PKI_SEND_FAIL_PUBLIC_KEY: Routing.Error.ValueType # 39
"""
PKI encryption failed, due to no public key for the remote node
This is different from PKI_UNKNOWN_PUBKEY which indicates a failure upon receiving a packet
"""
ROUTE_REQUEST_FIELD_NUMBER: builtins.int
ROUTE_REPLY_FIELD_NUMBER: builtins.int
@@ -2179,6 +2237,143 @@ class KeyVerification(google.protobuf.message.Message):
global___KeyVerification = KeyVerification
@typing.final
class StoreForwardPlusPlus(google.protobuf.message.Message):
"""
The actual over-the-mesh message doing store and forward++
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _SFPP_message_type:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _SFPP_message_typeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[StoreForwardPlusPlus._SFPP_message_type.ValueType], builtins.type):
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
CANON_ANNOUNCE: StoreForwardPlusPlus._SFPP_message_type.ValueType # 0
"""
Send an announcement of the canonical tip of a chain
"""
CHAIN_QUERY: StoreForwardPlusPlus._SFPP_message_type.ValueType # 1
"""
Query whether a specific link is on the chain
"""
LINK_REQUEST: StoreForwardPlusPlus._SFPP_message_type.ValueType # 3
"""
Request the next link in the chain
"""
LINK_PROVIDE: StoreForwardPlusPlus._SFPP_message_type.ValueType # 4
"""
Provide a link to add to the chain
"""
LINK_PROVIDE_FIRSTHALF: StoreForwardPlusPlus._SFPP_message_type.ValueType # 5
"""
If we must fragment, send the first half
"""
LINK_PROVIDE_SECONDHALF: StoreForwardPlusPlus._SFPP_message_type.ValueType # 6
"""
If we must fragment, send the second half
"""
class SFPP_message_type(_SFPP_message_type, metaclass=_SFPP_message_typeEnumTypeWrapper):
"""
Enum of message types
"""
CANON_ANNOUNCE: StoreForwardPlusPlus.SFPP_message_type.ValueType # 0
"""
Send an announcement of the canonical tip of a chain
"""
CHAIN_QUERY: StoreForwardPlusPlus.SFPP_message_type.ValueType # 1
"""
Query whether a specific link is on the chain
"""
LINK_REQUEST: StoreForwardPlusPlus.SFPP_message_type.ValueType # 3
"""
Request the next link in the chain
"""
LINK_PROVIDE: StoreForwardPlusPlus.SFPP_message_type.ValueType # 4
"""
Provide a link to add to the chain
"""
LINK_PROVIDE_FIRSTHALF: StoreForwardPlusPlus.SFPP_message_type.ValueType # 5
"""
If we must fragment, send the first half
"""
LINK_PROVIDE_SECONDHALF: StoreForwardPlusPlus.SFPP_message_type.ValueType # 6
"""
If we must fragment, send the second half
"""
SFPP_MESSAGE_TYPE_FIELD_NUMBER: builtins.int
MESSAGE_HASH_FIELD_NUMBER: builtins.int
COMMIT_HASH_FIELD_NUMBER: builtins.int
ROOT_HASH_FIELD_NUMBER: builtins.int
MESSAGE_FIELD_NUMBER: builtins.int
ENCAPSULATED_ID_FIELD_NUMBER: builtins.int
ENCAPSULATED_TO_FIELD_NUMBER: builtins.int
ENCAPSULATED_FROM_FIELD_NUMBER: builtins.int
ENCAPSULATED_RXTIME_FIELD_NUMBER: builtins.int
CHAIN_COUNT_FIELD_NUMBER: builtins.int
sfpp_message_type: global___StoreForwardPlusPlus.SFPP_message_type.ValueType
"""
Which message type is this
"""
message_hash: builtins.bytes
"""
The hash of the specific message
"""
commit_hash: builtins.bytes
"""
The hash of a link on a chain
"""
root_hash: builtins.bytes
"""
the root hash of a chain
"""
message: builtins.bytes
"""
The encrypted bytes from a message
"""
encapsulated_id: builtins.int
"""
Message ID of the contained message
"""
encapsulated_to: builtins.int
"""
Destination of the contained message
"""
encapsulated_from: builtins.int
"""
Sender of the contained message
"""
encapsulated_rxtime: builtins.int
"""
The receive time of the message in question
"""
chain_count: builtins.int
"""
Used in a LINK_REQUEST to specify the message X spots back from head
"""
def __init__(
self,
*,
sfpp_message_type: global___StoreForwardPlusPlus.SFPP_message_type.ValueType = ...,
message_hash: builtins.bytes = ...,
commit_hash: builtins.bytes = ...,
root_hash: builtins.bytes = ...,
message: builtins.bytes = ...,
encapsulated_id: builtins.int = ...,
encapsulated_to: builtins.int = ...,
encapsulated_from: builtins.int = ...,
encapsulated_rxtime: builtins.int = ...,
chain_count: builtins.int = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["chain_count", b"chain_count", "commit_hash", b"commit_hash", "encapsulated_from", b"encapsulated_from", "encapsulated_id", b"encapsulated_id", "encapsulated_rxtime", b"encapsulated_rxtime", "encapsulated_to", b"encapsulated_to", "message", b"message", "message_hash", b"message_hash", "root_hash", b"root_hash", "sfpp_message_type", b"sfpp_message_type"]) -> None: ...
global___StoreForwardPlusPlus = StoreForwardPlusPlus
@typing.final
class Waypoint(google.protobuf.message.Message):
"""
@@ -2249,6 +2444,25 @@ class Waypoint(google.protobuf.message.Message):
global___Waypoint = Waypoint
@typing.final
class StatusMessage(google.protobuf.message.Message):
"""
Message for node status
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
STATUS_FIELD_NUMBER: builtins.int
status: builtins.str
def __init__(
self,
*,
status: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["status", b"status"]) -> None: ...
global___StatusMessage = StatusMessage
@typing.final
class MqttClientProxyMessage(google.protobuf.message.Message):
"""
@@ -2557,6 +2771,10 @@ class MeshPacket(google.protobuf.message.Message):
to: builtins.int
"""
The (immediate) destination for this packet
If the value is 4,294,967,295 (maximum value of an unsigned 32bit integer), this indicates that the packet was
not destined for a specific node, but for a channel as indicated by the value of `channel` below.
If the value is another, this indicates that the packet was destined for a specific
node (i.e. a kind of "Direct Message" to this node) and not broadcast on a channel.
"""
channel: builtins.int
"""
@@ -2736,6 +2954,7 @@ class NodeInfo(google.protobuf.message.Message):
IS_FAVORITE_FIELD_NUMBER: builtins.int
IS_IGNORED_FIELD_NUMBER: builtins.int
IS_KEY_MANUALLY_VERIFIED_FIELD_NUMBER: builtins.int
IS_MUTED_FIELD_NUMBER: builtins.int
num: builtins.int
"""
The node number
@@ -2783,6 +3002,11 @@ class NodeInfo(google.protobuf.message.Message):
Persists between NodeDB internal clean ups
LSB 0 of the bitfield
"""
is_muted: builtins.bool
"""
True if node has been muted
Persistes between NodeDB internal clean ups
"""
@property
def user(self) -> global___User:
"""
@@ -2817,9 +3041,10 @@ class NodeInfo(google.protobuf.message.Message):
is_favorite: builtins.bool = ...,
is_ignored: builtins.bool = ...,
is_key_manually_verified: builtins.bool = ...,
is_muted: 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", "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 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", "is_muted", b"is_muted", "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

View File

File diff suppressed because one or more lines are too long

View File

@@ -568,6 +568,12 @@ class ModuleConfig(google.protobuf.message.Message):
"""Used to configure and view some parameters of MeshSolar.
https://heltec.org/project/meshsolar/
"""
LOG: ModuleConfig.SerialConfig._Serial_Mode.ValueType # 9
"""Logs mesh traffic to the serial pins, ideal for logging via openLog or similar.
includes other packets
"""
LOGTEXT: ModuleConfig.SerialConfig._Serial_Mode.ValueType # 10
"""only text (channel & DM)"""
class Serial_Mode(_Serial_Mode, metaclass=_Serial_ModeEnumTypeWrapper):
"""
@@ -591,6 +597,12 @@ class ModuleConfig(google.protobuf.message.Message):
"""Used to configure and view some parameters of MeshSolar.
https://heltec.org/project/meshsolar/
"""
LOG: ModuleConfig.SerialConfig.Serial_Mode.ValueType # 9
"""Logs mesh traffic to the serial pins, ideal for logging via openLog or similar.
includes other packets
"""
LOGTEXT: ModuleConfig.SerialConfig.Serial_Mode.ValueType # 10
"""only text (channel & DM)"""
ENABLED_FIELD_NUMBER: builtins.int
ECHO_FIELD_NUMBER: builtins.int
@@ -875,6 +887,7 @@ class ModuleConfig(google.protobuf.message.Message):
HEALTH_UPDATE_INTERVAL_FIELD_NUMBER: builtins.int
HEALTH_SCREEN_ENABLED_FIELD_NUMBER: builtins.int
DEVICE_TELEMETRY_ENABLED_FIELD_NUMBER: builtins.int
AIR_QUALITY_SCREEN_ENABLED_FIELD_NUMBER: builtins.int
device_update_interval: builtins.int
"""
Interval in seconds of how often we should try to send our
@@ -940,6 +953,10 @@ class ModuleConfig(google.protobuf.message.Message):
Enable/Disable the device telemetry module to send metrics to the mesh
Note: We will still send telemtry to the connected phone / client every minute over the API
"""
air_quality_screen_enabled: builtins.bool
"""
Enable/Disable the air quality telemetry measurement module on-device display
"""
def __init__(
self,
*,
@@ -957,8 +974,9 @@ class ModuleConfig(google.protobuf.message.Message):
health_update_interval: builtins.int = ...,
health_screen_enabled: builtins.bool = ...,
device_telemetry_enabled: builtins.bool = ...,
air_quality_screen_enabled: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["air_quality_enabled", b"air_quality_enabled", "air_quality_interval", b"air_quality_interval", "device_telemetry_enabled", b"device_telemetry_enabled", "device_update_interval", b"device_update_interval", "environment_display_fahrenheit", b"environment_display_fahrenheit", "environment_measurement_enabled", b"environment_measurement_enabled", "environment_screen_enabled", b"environment_screen_enabled", "environment_update_interval", b"environment_update_interval", "health_measurement_enabled", b"health_measurement_enabled", "health_screen_enabled", b"health_screen_enabled", "health_update_interval", b"health_update_interval", "power_measurement_enabled", b"power_measurement_enabled", "power_screen_enabled", b"power_screen_enabled", "power_update_interval", b"power_update_interval"]) -> None: ...
def ClearField(self, field_name: typing.Literal["air_quality_enabled", b"air_quality_enabled", "air_quality_interval", b"air_quality_interval", "air_quality_screen_enabled", b"air_quality_screen_enabled", "device_telemetry_enabled", b"device_telemetry_enabled", "device_update_interval", b"device_update_interval", "environment_display_fahrenheit", b"environment_display_fahrenheit", "environment_measurement_enabled", b"environment_measurement_enabled", "environment_screen_enabled", b"environment_screen_enabled", "environment_update_interval", b"environment_update_interval", "health_measurement_enabled", b"health_measurement_enabled", "health_screen_enabled", b"health_screen_enabled", "health_update_interval", b"health_update_interval", "power_measurement_enabled", b"power_measurement_enabled", "power_screen_enabled", b"power_screen_enabled", "power_update_interval", b"power_update_interval"]) -> None: ...
@typing.final
class CannedMessageConfig(google.protobuf.message.Message):
@@ -1164,6 +1182,26 @@ class ModuleConfig(google.protobuf.message.Message):
) -> None: ...
def ClearField(self, field_name: typing.Literal["blue", b"blue", "current", b"current", "green", b"green", "led_state", b"led_state", "red", b"red"]) -> None: ...
@typing.final
class StatusMessageConfig(google.protobuf.message.Message):
"""
StatusMessage config - Allows setting a status message for a node to periodically rebroadcast
"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
NODE_STATUS_FIELD_NUMBER: builtins.int
node_status: builtins.str
"""
The actual status string
"""
def __init__(
self,
*,
node_status: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing.Literal["node_status", b"node_status"]) -> None: ...
MQTT_FIELD_NUMBER: builtins.int
SERIAL_FIELD_NUMBER: builtins.int
EXTERNAL_NOTIFICATION_FIELD_NUMBER: builtins.int
@@ -1177,6 +1215,7 @@ class ModuleConfig(google.protobuf.message.Message):
AMBIENT_LIGHTING_FIELD_NUMBER: builtins.int
DETECTION_SENSOR_FIELD_NUMBER: builtins.int
PAXCOUNTER_FIELD_NUMBER: builtins.int
STATUSMESSAGE_FIELD_NUMBER: builtins.int
@property
def mqtt(self) -> global___ModuleConfig.MQTTConfig:
"""
@@ -1255,6 +1294,12 @@ class ModuleConfig(google.protobuf.message.Message):
TODO: REPLACE
"""
@property
def statusmessage(self) -> global___ModuleConfig.StatusMessageConfig:
"""
TODO: REPLACE
"""
def __init__(
self,
*,
@@ -1271,10 +1316,11 @@ class ModuleConfig(google.protobuf.message.Message):
ambient_lighting: global___ModuleConfig.AmbientLightingConfig | None = ...,
detection_sensor: global___ModuleConfig.DetectionSensorConfig | None = ...,
paxcounter: global___ModuleConfig.PaxcounterConfig | None = ...,
statusmessage: global___ModuleConfig.StatusMessageConfig | None = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "payload_variant", b"payload_variant", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "payload_variant", b"payload_variant", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["mqtt", "serial", "external_notification", "store_forward", "range_test", "telemetry", "canned_message", "audio", "remote_hardware", "neighbor_info", "ambient_lighting", "detection_sensor", "paxcounter"] | None: ...
def HasField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "payload_variant", b"payload_variant", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "statusmessage", b"statusmessage", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["ambient_lighting", b"ambient_lighting", "audio", b"audio", "canned_message", b"canned_message", "detection_sensor", b"detection_sensor", "external_notification", b"external_notification", "mqtt", b"mqtt", "neighbor_info", b"neighbor_info", "paxcounter", b"paxcounter", "payload_variant", b"payload_variant", "range_test", b"range_test", "remote_hardware", b"remote_hardware", "serial", b"serial", "statusmessage", b"statusmessage", "store_forward", b"store_forward", "telemetry", b"telemetry"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["payload_variant", b"payload_variant"]) -> typing.Literal["mqtt", "serial", "external_notification", "store_forward", "range_test", "telemetry", "canned_message", "audio", "remote_hardware", "neighbor_info", "ambient_lighting", "detection_sensor", "paxcounter", "statusmessage"] | None: ...
global___ModuleConfig = ModuleConfig

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*\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\x14org.meshtastic.protoB\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*\xab\x05\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\x1e\n\x1aSTORE_FORWARD_PLUSPLUS_APP\x10#\x12\x13\n\x0fNODE_STATUS_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\x14org.meshtastic.protoB\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\024org.meshtastic.protoB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_PORTNUM']._serialized_start=60
_globals['_PORTNUM']._serialized_end=690
_globals['_PORTNUM']._serialized_end=743
# @@protoc_insertion_point(module_scope)

View File

@@ -117,6 +117,20 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy
Paxcounter lib included in the firmware
ENCODING: protobuf
"""
STORE_FORWARD_PLUSPLUS_APP: _PortNum.ValueType # 35
"""
Store and Forward++ module included in the firmware
ENCODING: protobuf
This module is specifically for Native Linux nodes, and provides a Git-style
chain of messages.
"""
NODE_STATUS_APP: _PortNum.ValueType # 36
"""
Node Status module
ENCODING: protobuf
This module allows setting an extra string of status for a node.
Broadcasts on change and on a timer, possibly once a day.
"""
SERIAL_APP: _PortNum.ValueType # 64
"""
Provides a hardware serial interface to send and receive from the Meshtastic network.
@@ -321,6 +335,20 @@ PAXCOUNTER_APP: PortNum.ValueType # 34
Paxcounter lib included in the firmware
ENCODING: protobuf
"""
STORE_FORWARD_PLUSPLUS_APP: PortNum.ValueType # 35
"""
Store and Forward++ module included in the firmware
ENCODING: protobuf
This module is specifically for Native Linux nodes, and provides a Git-style
chain of messages.
"""
NODE_STATUS_APP: PortNum.ValueType # 36
"""
Node Status module
ENCODING: protobuf
This module allows setting an extra string of status for a node.
Broadcasts on change and on a timer, possibly once a day.
"""
SERIAL_APP: PortNum.ValueType # 64
"""
Provides a hardware serial interface to send and receive from the Meshtastic network.

View File

File diff suppressed because one or more lines are too long

View File

@@ -1035,6 +1035,7 @@ class LocalStats(google.protobuf.message.Message):
HEAP_TOTAL_BYTES_FIELD_NUMBER: builtins.int
HEAP_FREE_BYTES_FIELD_NUMBER: builtins.int
NUM_TX_DROPPED_FIELD_NUMBER: builtins.int
NOISE_FLOOR_FIELD_NUMBER: builtins.int
uptime_seconds: builtins.int
"""
How long the device has been running since the last reboot (in seconds)
@@ -1093,6 +1094,10 @@ class LocalStats(google.protobuf.message.Message):
"""
Number of packets that were dropped because the transmit queue was full.
"""
noise_floor: builtins.int
"""
Noise floor value measured in dBm
"""
def __init__(
self,
*,
@@ -1110,8 +1115,9 @@ class LocalStats(google.protobuf.message.Message):
heap_total_bytes: builtins.int = ...,
heap_free_bytes: builtins.int = ...,
num_tx_dropped: builtins.int = ...,
noise_floor: builtins.int = ...,
) -> 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_dropped", b"num_tx_dropped", "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", "noise_floor", b"noise_floor", "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_dropped", b"num_tx_dropped", "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

View File

@@ -0,0 +1,221 @@
"""Meshtastic unit tests for showNodes favorite column feature"""
from unittest.mock import MagicMock
import pytest
from ..mesh_interface import MeshInterface
@pytest.fixture
def _iface_with_favorite_nodes():
"""Fixture to setup nodes with favorite flags."""
nodesById = {
"!9388f81c": {
"num": 2475227164,
"user": {
"id": "!9388f81c",
"longName": "Favorite Node",
"shortName": "FAV1",
"macaddr": "RBeTiPgc",
"hwModel": "TBEAM",
},
"position": {},
"lastHeard": 1640204888,
"isFavorite": True,
},
"!12345678": {
"num": 305419896,
"user": {
"id": "!12345678",
"longName": "Regular Node",
"shortName": "REG1",
"macaddr": "ABCDEFGH",
"hwModel": "TLORA_V2",
},
"position": {},
"lastHeard": 1640204999,
"isFavorite": False,
},
"!abcdef00": {
"num": 2882400000,
"user": {
"id": "!abcdef00",
"longName": "Legacy Node",
"shortName": "LEG1",
"macaddr": "XYZABC00",
"hwModel": "HELTEC_V3",
},
"position": {},
"lastHeard": 1640205000,
# Note: No isFavorite field - testing backward compatibility
},
}
nodesByNum = {
2475227164: {
"num": 2475227164,
"user": {
"id": "!9388f81c",
"longName": "Favorite Node",
"shortName": "FAV1",
"macaddr": "RBeTiPgc",
"hwModel": "TBEAM",
},
"position": {"time": 1640206266},
"lastHeard": 1640206266,
"isFavorite": True,
},
305419896: {
"num": 305419896,
"user": {
"id": "!12345678",
"longName": "Regular Node",
"shortName": "REG1",
"macaddr": "ABCDEFGH",
"hwModel": "TLORA_V2",
},
"position": {"time": 1640206200},
"lastHeard": 1640206200,
"isFavorite": False,
},
2882400000: {
"num": 2882400000,
"user": {
"id": "!abcdef00",
"longName": "Legacy Node",
"shortName": "LEG1",
"macaddr": "XYZABC00",
"hwModel": "HELTEC_V3",
},
"position": {"time": 1640206100},
"lastHeard": 1640206100,
# Note: No isFavorite field - testing backward compatibility
},
}
iface = MeshInterface(noProto=True)
iface.nodes = nodesById
iface.nodesByNum = nodesByNum
myInfo = MagicMock()
iface.myInfo = myInfo
iface.myInfo.my_node_num = 2475227164
return iface
@pytest.mark.unit
def test_showNodes_favorite_column_header(capsys, _iface_with_favorite_nodes):
"""Test that 'Fav' column header appears in showNodes output"""
iface = _iface_with_favorite_nodes
iface.showNodes()
out, err = capsys.readouterr()
assert "Fav" in out
assert err == ""
@pytest.mark.unit
def test_showNodes_favorite_asterisk_display(capsys, _iface_with_favorite_nodes):
"""Test that favorite nodes show asterisk and non-favorites show empty"""
iface = _iface_with_favorite_nodes
iface.showNodes()
out, err = capsys.readouterr()
# Check that the output contains the "Fav" column
assert "Fav" in out
# Find lines containing our nodes
lines = out.split('\n')
favorite_line = None
regular_line = None
legacy_line = None
for line in lines:
if "Favorite Node" in line or "FAV1" in line:
favorite_line = line
if "Regular Node" in line or "REG1" in line:
regular_line = line
if "Legacy Node" in line or "LEG1" in line:
legacy_line = line
# Verify all nodes are present in the output
assert favorite_line is not None, "Favorite node should be in output"
assert regular_line is not None, "Regular node should be in output"
assert legacy_line is not None, "Legacy node should be in output"
# Verify the favorite node has an asterisk in its row
assert "*" in favorite_line, "Favorite node should have an asterisk"
# Verify the regular (non-favorite) node does NOT have an asterisk
assert regular_line.count("*") == 0, "Non-favorite node should not have an asterisk"
# Verify the legacy node (without isFavorite field) does NOT have an asterisk
assert legacy_line.count("*") == 0, "Legacy node without isFavorite field should not have an asterisk"
assert err == ""
@pytest.mark.unit
def test_showNodes_favorite_field_formatting():
"""Test the formatting logic for isFavorite field"""
# Test favorite node
raw_value = True
formatted_value = "*" if raw_value else ""
assert formatted_value == "*"
# Test non-favorite node
raw_value = False
formatted_value = "*" if raw_value else ""
assert formatted_value == ""
# Test None/missing value
raw_value = None
formatted_value = "*" if raw_value else ""
assert formatted_value == ""
@pytest.mark.unit
def test_showNodes_with_custom_fields_including_favorite(capsys, _iface_with_favorite_nodes):
"""Test that isFavorite can be specified in custom showFields"""
iface = _iface_with_favorite_nodes
custom_fields = ["user.longName", "isFavorite"]
iface.showNodes(showFields=custom_fields)
out, err = capsys.readouterr()
# Should still show the Fav column when explicitly requested
assert "Fav" in out
assert err == ""
@pytest.mark.unit
def test_showNodes_default_fields_includes_favorite(_iface_with_favorite_nodes):
"""Test that isFavorite is included in default fields"""
iface = _iface_with_favorite_nodes
# Call showNodes which uses default fields
result = iface.showNodes()
# The result should contain the formatted table as a string
assert "Fav" in result
@pytest.mark.unit
def test_showNodes_backward_compatibility_missing_field(capsys, _iface_with_favorite_nodes):
"""Test that nodes without isFavorite field are handled gracefully"""
iface = _iface_with_favorite_nodes
iface.showNodes()
out, err = capsys.readouterr()
# Find the legacy node line
lines = out.split('\n')
legacy_line = None
for line in lines:
if "Legacy Node" in line or "LEG1" in line:
legacy_line = line
break
# Verify the legacy node appears in output
assert legacy_line is not None, "Legacy node without isFavorite field should appear in output"
# Verify it doesn't have an asterisk (should be treated as non-favorite)
assert legacy_line.count("*") == 0, "Legacy node should not have asterisk (treated as non-favorite)"
assert err == ""

View File

@@ -735,3 +735,16 @@ def to_node_num(node_id: Union[int, str]) -> int:
return int(s, 10)
except ValueError:
return int(s, 16)
def flags_to_list(flag_type, flags: int) -> List[str]:
"""Given a flag_type that's a protobuf EnumTypeWrapper, and a flag int, give a list of flags enabled."""
ret = []
for key in flag_type.keys():
if key == "EXCLUDED_NONE":
continue
if flags & flag_type.Value(key):
ret.append(key)
flags = flags - flag_type.Value(key)
if flags > 0:
ret.append(f"UNKNOWN_ADDITIONAL_FLAGS({flags})")
return ret

44
poetry.lock generated
View File

@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
[[package]]
name = "altgraph"
@@ -3438,7 +3438,7 @@ description = "Type annotations for pandas"
optional = true
python-versions = ">=3.9"
groups = ["main"]
markers = "python_version < \"3.11\" and extra == \"analysis\""
markers = "extra == \"analysis\""
files = [
{file = "pandas_stubs-2.2.2.240807-py3-none-any.whl", hash = "sha256:893919ad82be4275f0d07bb47a95d08bae580d3fdea308a7acfcb3f02e76186e"},
{file = "pandas_stubs-2.2.2.240807.tar.gz", hash = "sha256:64a559725a57a449f46225fbafc422520b7410bff9252b661a225b5559192a93"},
@@ -3448,23 +3448,6 @@ files = [
numpy = ">=1.23.5"
types-pytz = ">=2022.1.1"
[[package]]
name = "pandas-stubs"
version = "2.3.2.250926"
description = "Type annotations for pandas"
optional = true
python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"analysis\" and python_version >= \"3.11\""
files = [
{file = "pandas_stubs-2.3.2.250926-py3-none-any.whl", hash = "sha256:81121818453dcfe00f45c852f4dceee043640b813830f6e7bd084a4ef7ff7270"},
{file = "pandas_stubs-2.3.2.250926.tar.gz", hash = "sha256:c64b9932760ceefb96a3222b953e6a251321a9832a28548be6506df473a66406"},
]
[package.dependencies]
numpy = ">=1.23.5"
types-pytz = ">=2022.1.1"
[[package]]
name = "pandocfilters"
version = "1.5.1"
@@ -3935,22 +3918,22 @@ wcwidth = "*"
[[package]]
name = "protobuf"
version = "6.33.0"
version = "6.33.5"
description = ""
optional = false
python-versions = ">=3.9"
groups = ["main", "dev"]
files = [
{file = "protobuf-6.33.0-cp310-abi3-win32.whl", hash = "sha256:d6101ded078042a8f17959eccd9236fb7a9ca20d3b0098bbcb91533a5680d035"},
{file = "protobuf-6.33.0-cp310-abi3-win_amd64.whl", hash = "sha256:9a031d10f703f03768f2743a1c403af050b6ae1f3480e9c140f39c45f81b13ee"},
{file = "protobuf-6.33.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:905b07a65f1a4b72412314082c7dbfae91a9e8b68a0cc1577515f8df58ecf455"},
{file = "protobuf-6.33.0-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e0697ece353e6239b90ee43a9231318302ad8353c70e6e45499fa52396debf90"},
{file = "protobuf-6.33.0-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:e0a1715e4f27355afd9570f3ea369735afc853a6c3951a6afe1f80d8569ad298"},
{file = "protobuf-6.33.0-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:35be49fd3f4fefa4e6e2aacc35e8b837d6703c37a2168a55ac21e9b1bc7559ef"},
{file = "protobuf-6.33.0-cp39-cp39-win32.whl", hash = "sha256:cd33a8e38ea3e39df66e1bbc462b076d6e5ba3a4ebbde58219d777223a7873d3"},
{file = "protobuf-6.33.0-cp39-cp39-win_amd64.whl", hash = "sha256:c963e86c3655af3a917962c9619e1a6b9670540351d7af9439d06064e3317cc9"},
{file = "protobuf-6.33.0-py3-none-any.whl", hash = "sha256:25c9e1963c6734448ea2d308cfa610e692b801304ba0908d7bfa564ac5132995"},
{file = "protobuf-6.33.0.tar.gz", hash = "sha256:140303d5c8d2037730c548f8c7b93b20bb1dc301be280c378b82b8894589c954"},
{file = "protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b"},
{file = "protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c"},
{file = "protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5"},
{file = "protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190"},
{file = "protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd"},
{file = "protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0"},
{file = "protobuf-6.33.5-cp39-cp39-win32.whl", hash = "sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c"},
{file = "protobuf-6.33.5-cp39-cp39-win_amd64.whl", hash = "sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a"},
{file = "protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02"},
{file = "protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c"},
]
[[package]]
@@ -4309,6 +4292,7 @@ python-versions = ">=3.3, <4"
groups = ["main"]
files = [
{file = "Pypubsub-4.0.3-py3-none-any.whl", hash = "sha256:7f716bae9388afe01ff82b264ba8a96a8ae78b42bb1f114f2716ca8f9e404e2a"},
{file = "pypubsub-4.0.3.tar.gz", hash = "sha256:32d662de3ade0fb0880da92df209c62a4803684de5ccb8d19421c92747a258c7"},
]
[[package]]

View File

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