Merge pull request #922 from ianmcorvidae/nanopb-options-inject

Inject options in nanopb .options files into the protobuf files used for code generation
This commit is contained in:
Ian McEwen
2026-05-31 10:27:27 -07:00
committed by GitHub
23 changed files with 1944 additions and 458 deletions

View File

@@ -0,0 +1,332 @@
#!/usr/bin/env python3
"""Inject nanopb .options constraints as inline field options into a .proto file.
The nanopb .options file format is specific to the nanopb C generator and is
ignored by standard protoc (including --python_out). By injecting the options
directly into the proto file's field declarations, protoc will embed them in
the serialized descriptor, making them accessible in Python via:
from meshtastic.protobuf import mesh_pb2, nanopb_pb2
field = mesh_pb2.DESCRIPTOR.message_types_by_name['User'].fields_by_name['long_name']
opts = field.GetOptions().Extensions[nanopb_pb2.nanopb]
print(opts.max_size) # 40
Usage:
inject_nanopb_options.py <options_file> <proto_file>
The proto_file is modified in-place. Intended to operate on temporary copies
generated by regen-protobufs.sh, not the source .proto files.
"""
import re
import sys
from pathlib import Path
from typing import Any, Dict, List, Tuple
# IntSize enum values from nanopb.proto
INT_SIZE_ENUM = {8: "IS_8", 16: "IS_16", 32: "IS_32", 64: "IS_64"}
# Options that are valid proto FieldOptions and useful outside of C code generation.
# We skip C-only options (anonymous_oneof, no_unions, skip_message, packed_struct,
# packed_enum, mangle_names, callback_datatype, callback_function, descriptorsize,
# type_override) since they either don't apply to proto fields or are C-specific.
FIELD_OPTIONS = frozenset(
{
"max_size",
"max_length",
"max_count",
"int_size",
"fixed_length",
"fixed_count",
"long_names",
"proto3",
"default_has",
"sort_by_tag",
"msgid",
}
)
def parse_value(s: str) -> Any:
"""Convert an option value string to an appropriate Python type."""
if re.fullmatch(r"-?[0-9]+", s):
return int(s)
if s.lower() == "true":
return True
if s.lower() == "false":
return False
return s
def parse_options_file(
path: Path,
) -> Tuple[Dict[Tuple[str, ...], Dict[str, Any]], Dict[str, Dict[str, Any]]]:
"""Parse a nanopb .options file.
Returns:
specific: maps (message_path..., field_name) -> {option: value}
e.g. ('User', 'long_name') or ('Route', 'Link', 'uid')
wildcard: maps field_name -> {option: value}
applies to any field with this name in the same proto file
"""
specific: Dict[Tuple[str, ...], Dict[str, Any]] = {}
wildcard: Dict[str, Dict[str, Any]] = {}
with open(path, encoding="utf-8") as f:
for line in f:
# Strip inline comments
comment_pos = line.find("#")
if comment_pos >= 0:
line = line[:comment_pos]
line = line.strip().lstrip("*").strip()
if not line:
continue
tokens = line.split()
if len(tokens) < 2:
continue
pattern = tokens[0]
opts: Dict[str, Any] = {}
for tok in tokens[1:]:
if ":" in tok:
k, v = tok.split(":", 1)
if k in FIELD_OPTIONS:
opts[k] = parse_value(v)
if not opts:
continue
if "." in pattern:
# e.g. "User.long_name" -> key=('User', 'long_name')
# or "Route.Link.uid" -> key=('Route', 'Link', 'uid')
parts = tuple(pattern.split("."))
if parts in specific:
specific[parts].update(opts)
else:
specific[parts] = opts
else:
# wildcard: applies to any field with this name
if pattern in wildcard:
wildcard[pattern].update(opts)
else:
wildcard[pattern] = opts
return specific, wildcard
def format_nanopb_opts(opts: Dict[str, Any]) -> str:
"""Format a dict of nanopb options as a proto field options annotation string."""
parts = []
for k, v in opts.items():
if k == "int_size":
enum_val = INT_SIZE_ENUM.get(v, f"IS_{v}")
parts.append(f"(nanopb).int_size = {enum_val}")
elif isinstance(v, bool):
parts.append(f"(nanopb).{k} = {'true' if v else 'false'}")
else:
parts.append(f"(nanopb).{k} = {v}")
return ", ".join(parts)
def message_path_matches(
context_stack: List[Tuple[str, str]], msg_path: Tuple[str, ...]
) -> bool:
"""Check if the current message context ends with msg_path.
context_stack entries are ('message'|'oneof'|'enum', name).
msg_path is the tuple of message names from the options pattern,
e.g. ('User',) or ('Route', 'Link').
"""
msg_names = [name for kind, name in context_stack if kind == "message"]
n = len(msg_path)
return len(msg_names) >= n and tuple(msg_names[-n:]) == msg_path
def inject_into_proto(
content: str,
specific: Dict[Tuple[str, ...], Dict[str, Any]],
wildcard: Dict[str, Dict[str, Any]],
nanopb_import_path: str,
) -> str:
"""Inject nanopb field options into a proto file's text content.
Adds an import for nanopb.proto if not already present.
Returns the modified content.
"""
if not specific and not wildcard:
return content
lines = content.split("\n")
# Check if nanopb is already imported (after sed fixup, it will be
# 'meshtastic/protobuf/nanopb.proto')
nanopb_already_imported = any(
"nanopb.proto" in line
for line in lines
if line.strip().startswith("import")
)
# Track the index of the last import line so we can insert after it
last_import_idx = max(
(
i
for i, line in enumerate(lines)
if line.strip().startswith("import ") and line.strip().endswith(";")
),
default=-1,
)
# State
context_stack: List[Tuple[str, str]] = [] # ('message'|'oneof'|'enum', name)
result: List[str] = []
import_added = nanopb_already_imported
# Patterns for proto structural elements
message_re = re.compile(r"^(\s*)message\s+(\w+)\s*\{")
oneof_re = re.compile(r"^(\s*)oneof\s+(\w+)\s*\{")
enum_re = re.compile(r"^(\s*)enum\s+(\w+)\s*\{")
close_re = re.compile(r"^\s*\}")
# Pattern for field declarations:
# indent [optional|repeated] type name = number [options] ;
# We exclude map<> fields (different syntax, nanopb handles them differently)
# and enum value lines (no type keyword before the name).
field_re = re.compile(
r"^(\s*)" # (1) indent
r"(optional\s+|repeated\s+)?" # (2) optional qualifier
r"([\w.]+)\s+" # (3) field type (possibly qualified like google.protobuf.Any)
r"(\w+)\s*" # (4) field name
r"=\s*(\d+)" # (5) field number
r"(?:\s*\[([^\]]*)\])?" # (6) existing options, without brackets
r"\s*;" # trailing semicolon
)
for i, line in enumerate(lines):
# Insert nanopb import right after the last existing import line.
# Only do this when there IS an existing import (last_import_idx >= 0);
# if there are no imports we fall through to the syntax-line fallback below.
if not import_added and last_import_idx >= 0 and i == last_import_idx + 1:
result.append(f'import "{nanopb_import_path}";')
import_added = True
# --- Track message/oneof/enum nesting ---
m = message_re.match(line)
if m:
context_stack.append(("message", m.group(2)))
result.append(line)
continue
m = oneof_re.match(line)
if m:
context_stack.append(("oneof", m.group(2)))
result.append(line)
continue
m = enum_re.match(line)
if m:
context_stack.append(("enum", m.group(2)))
result.append(line)
continue
if close_re.match(line) and context_stack:
context_stack.pop()
result.append(line)
continue
# Skip field injection inside enum bodies (enum values look like fields
# but should not have nanopb options added)
in_enum = bool(context_stack) and context_stack[-1][0] == "enum"
# --- Try to match and modify a field declaration ---
m = field_re.match(line)
if m and not in_enum:
indent = m.group(1)
qualifier = m.group(2) or ""
ftype = m.group(3)
fname = m.group(4)
fnum = m.group(5)
existing_opts = m.group(6) or ""
# Collect applicable nanopb options (wildcard < specific)
extra: Dict[str, Any] = {}
# 1. Wildcard: any field with this name in this proto file
if fname in wildcard:
extra.update(wildcard[fname])
# 2. Specific: check all keys whose last element is fname and whose
# preceding path matches the current message context
for key, opts in specific.items():
if key[-1] == fname:
msg_path = key[:-1]
if message_path_matches(context_stack, msg_path):
extra.update(opts)
break
if extra:
nanopb_str = format_nanopb_opts(extra)
if existing_opts.strip():
opts_block = f"[{existing_opts}, {nanopb_str}]"
else:
opts_block = f"[{nanopb_str}]"
qual = qualifier.rstrip()
sep = " " if qual else ""
line = f"{indent}{qual}{sep}{ftype} {fname} = {fnum} {opts_block};"
result.append(line)
# Edge case: if there were no import lines, add nanopb import after syntax line
if not import_added:
for i, line in enumerate(result):
if line.strip().startswith("syntax") and line.strip().endswith(";"):
result.insert(i + 1, f'import "{nanopb_import_path}";')
break
return "\n".join(result)
def main() -> int:
"""Parse an .options file and inject its constraints into a .proto file in-place."""
if len(sys.argv) != 3:
print(
f"Usage: {sys.argv[0]} <options_file> <proto_file>",
file=sys.stderr,
)
return 1
opts_path = Path(sys.argv[1])
proto_path = Path(sys.argv[2])
if not opts_path.exists():
print(f"Options file not found: {opts_path}", file=sys.stderr)
return 1
if not proto_path.exists():
print(f"Proto file not found: {proto_path}", file=sys.stderr)
return 1
specific, wildcard = parse_options_file(opts_path)
total = len(specific) + len(wildcard)
if total == 0:
print(f" [{opts_path.name}] No injectable options found, skipping.")
return 0
content = proto_path.read_text(encoding="utf-8")
# After regen-protobufs.sh's sed fixup, the nanopb import path is:
nanopb_import_path = "meshtastic/protobuf/nanopb.proto"
modified = inject_into_proto(content, specific, wildcard, nanopb_import_path)
proto_path.write_text(modified, encoding="utf-8")
print(
f" [{opts_path.name}] Injected {len(specific)} specific + "
f"{len(wildcard)} wildcard option(s) into {proto_path.name}"
)
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@@ -46,6 +46,19 @@ $SEDCMD 's/^import "meshtastic\//import "meshtastic\/protobuf\//' "${INDIR}/"*.p
$SEDCMD 's/^import "nanopb.proto"/import "meshtastic\/protobuf\/nanopb.proto"/' "${INDIR}/"*.proto
# Inject nanopb .options constraints as inline proto field options so that
# protoc --python_out embeds them in the generated descriptors. Python code
# can then read them via:
# field.GetOptions().Extensions[nanopb_pb2.nanopb].max_size
echo "Injecting nanopb options into proto files..."
for OPTS_FILE in "${INDIR}"/*.options; do
BASENAME=$(basename "${OPTS_FILE}" .options)
PROTO_FILE="${INDIR}/${BASENAME}.proto"
if [ -f "${PROTO_FILE}" ]; then
python3 ./bin/inject_nanopb_options.py "${OPTS_FILE}" "${PROTO_FILE}"
fi
done
# Generate the python files
./nanopb-0.4.8/generator-bin/protoc -I=$TMPDIR/in --python_out "${OUTDIR}" "--mypy_out=${PYIDIR}" $INDIR/*.proto

View File

File diff suppressed because one or more lines are too long

View File

@@ -13,9 +13,10 @@ _sym_db = _symbol_database.Default()
from meshtastic.protobuf import channel_pb2 as meshtastic_dot_protobuf_dot_channel__pb2
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/apponly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\"\x81\x01\n\nChannelSet\x12\x36\n\x08settings\x18\x01 \x03(\x0b\x32$.meshtastic.protobuf.ChannelSettings\x12;\n\x0blora_config\x18\x02 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigBc\n\x14org.meshtastic.protoB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/apponly.proto\x12\x13meshtastic.protobuf\x1a!meshtastic/protobuf/channel.proto\x1a meshtastic/protobuf/config.proto\x1a meshtastic/protobuf/nanopb.proto\"\x88\x01\n\nChannelSet\x12=\n\x08settings\x18\x01 \x03(\x0b\x32$.meshtastic.protobuf.ChannelSettingsB\x05\x92?\x02\x10\x08\x12;\n\x0blora_config\x18\x02 \x01(\x0b\x32&.meshtastic.protobuf.Config.LoRaConfigBc\n\x14org.meshtastic.protoB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -23,6 +24,8 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.apponly
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_CHANNELSET']._serialized_start=128
_globals['_CHANNELSET']._serialized_end=257
_CHANNELSET.fields_by_name['settings']._options = None
_CHANNELSET.fields_by_name['settings']._serialized_options = b'\222?\002\020\010'
_globals['_CHANNELSET']._serialized_start=162
_globals['_CHANNELSET']._serialized_end=298
# @@protoc_insertion_point(module_scope)

View File

File diff suppressed because one or more lines are too long

View File

@@ -2795,7 +2795,6 @@ class CasevacReport(google.protobuf.message.Message):
non_us_military: builtins.int
non_us_civilian: builtins.int
epw: builtins.int
"""enemy prisoner of war"""
child: builtins.int
terrain_flags: builtins.int
"""

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(meshtastic/protobuf/cannedmessages.proto\x12\x13meshtastic.protobuf\"-\n\x19\x43\x61nnedMessageModuleConfig\x12\x10\n\x08messages\x18\x01 \x01(\tBo\n\x14org.meshtastic.protoB\x19\x43\x61nnedMessageConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(meshtastic/protobuf/cannedmessages.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"5\n\x19\x43\x61nnedMessageModuleConfig\x12\x18\n\x08messages\x18\x01 \x01(\tB\x06\x92?\x03\x08\xc9\x01\x42o\n\x14org.meshtastic.protoB\x19\x43\x61nnedMessageConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,6 +22,8 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.cannedm
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\031CannedMessageConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_CANNEDMESSAGEMODULECONFIG']._serialized_start=65
_globals['_CANNEDMESSAGEMODULECONFIG']._serialized_end=110
_CANNEDMESSAGEMODULECONFIG.fields_by_name['messages']._options = None
_CANNEDMESSAGEMODULECONFIG.fields_by_name['messages']._serialized_options = b'\222?\003\010\311\001'
_globals['_CANNEDMESSAGEMODULECONFIG']._serialized_start=99
_globals['_CANNEDMESSAGEMODULECONFIG']._serialized_end=152
# @@protoc_insertion_point(module_scope)

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/channel.proto\x12\x13meshtastic.protobuf\"\xc1\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x0b\n\x03psk\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\x12<\n\x0fmodule_settings\x18\x07 \x01(\x0b\x32#.meshtastic.protobuf.ModuleSettings\">\n\x0eModuleSettings\x12\x1a\n\x12position_precision\x18\x01 \x01(\r\x12\x10\n\x08is_muted\x18\x02 \x01(\x08\"\xb3\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12\x36\n\x08settings\x18\x02 \x01(\x0b\x32$.meshtastic.protobuf.ChannelSettings\x12/\n\x04role\x18\x03 \x01(\x0e\x32!.meshtastic.protobuf.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42\x63\n\x14org.meshtastic.protoB\rChannelProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!meshtastic/protobuf/channel.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"\xcf\x01\n\x0f\x43hannelSettings\x12\x17\n\x0b\x63hannel_num\x18\x01 \x01(\rB\x02\x18\x01\x12\x12\n\x03psk\x18\x02 \x01(\x0c\x42\x05\x92?\x02\x08 \x12\x13\n\x04name\x18\x03 \x01(\tB\x05\x92?\x02\x08\x0c\x12\n\n\x02id\x18\x04 \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x05 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x06 \x01(\x08\x12<\n\x0fmodule_settings\x18\x07 \x01(\x0b\x32#.meshtastic.protobuf.ModuleSettings\">\n\x0eModuleSettings\x12\x1a\n\x12position_precision\x18\x01 \x01(\r\x12\x10\n\x08is_muted\x18\x02 \x01(\x08\"\xba\x01\n\x07\x43hannel\x12\x14\n\x05index\x18\x01 \x01(\x05\x42\x05\x92?\x02\x38\x08\x12\x36\n\x08settings\x18\x02 \x01(\x0b\x32$.meshtastic.protobuf.ChannelSettings\x12/\n\x04role\x18\x03 \x01(\x0e\x32!.meshtastic.protobuf.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42\x63\n\x14org.meshtastic.protoB\rChannelProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -23,12 +24,18 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\rChannelProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_CHANNELSETTINGS.fields_by_name['channel_num']._options = None
_CHANNELSETTINGS.fields_by_name['channel_num']._serialized_options = b'\030\001'
_globals['_CHANNELSETTINGS']._serialized_start=59
_globals['_CHANNELSETTINGS']._serialized_end=252
_globals['_MODULESETTINGS']._serialized_start=254
_globals['_MODULESETTINGS']._serialized_end=316
_globals['_CHANNEL']._serialized_start=319
_globals['_CHANNEL']._serialized_end=498
_globals['_CHANNEL_ROLE']._serialized_start=450
_globals['_CHANNEL_ROLE']._serialized_end=498
_CHANNELSETTINGS.fields_by_name['psk']._options = None
_CHANNELSETTINGS.fields_by_name['psk']._serialized_options = b'\222?\002\010 '
_CHANNELSETTINGS.fields_by_name['name']._options = None
_CHANNELSETTINGS.fields_by_name['name']._serialized_options = b'\222?\002\010\014'
_CHANNEL.fields_by_name['index']._options = None
_CHANNEL.fields_by_name['index']._serialized_options = b'\222?\0028\010'
_globals['_CHANNELSETTINGS']._serialized_start=93
_globals['_CHANNELSETTINGS']._serialized_end=300
_globals['_MODULESETTINGS']._serialized_start=302
_globals['_MODULESETTINGS']._serialized_end=364
_globals['_CHANNEL']._serialized_start=367
_globals['_CHANNEL']._serialized_end=553
_globals['_CHANNEL_ROLE']._serialized_start=505
_globals['_CHANNEL_ROLE']._serialized_end=553
# @@protoc_insertion_point(module_scope)

View File

@@ -13,9 +13,10 @@ _sym_db = _symbol_database.Default()
from meshtastic.protobuf import localonly_pb2 as meshtastic_dot_protobuf_dot_localonly__pb2
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/clientonly.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\"\xc4\x03\n\rDeviceProfile\x12\x16\n\tlong_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nshort_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x63hannel_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x35\n\x06\x63onfig\x18\x04 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfigH\x03\x88\x01\x01\x12\x42\n\rmodule_config\x18\x05 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfigH\x04\x88\x01\x01\x12:\n\x0e\x66ixed_position\x18\x06 \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x05\x88\x01\x01\x12\x15\n\x08ringtone\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1c\n\x0f\x63\x61nned_messages\x18\x08 \x01(\tH\x07\x88\x01\x01\x42\x0c\n\n_long_nameB\r\n\x0b_short_nameB\x0e\n\x0c_channel_urlB\t\n\x07_configB\x10\n\x0e_module_configB\x11\n\x0f_fixed_positionB\x0b\n\t_ringtoneB\x12\n\x10_canned_messagesBf\n\x14org.meshtastic.protoB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/clientonly.proto\x12\x13meshtastic.protobuf\x1a#meshtastic/protobuf/localonly.proto\x1a\x1emeshtastic/protobuf/mesh.proto\x1a meshtastic/protobuf/nanopb.proto\"\xe2\x03\n\rDeviceProfile\x12\x1d\n\tlong_name\x18\x01 \x01(\tB\x05\x92?\x02\x08(H\x00\x88\x01\x01\x12\x1e\n\nshort_name\x18\x02 \x01(\tB\x05\x92?\x02\x08\x05H\x01\x88\x01\x01\x12\x18\n\x0b\x63hannel_url\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x35\n\x06\x63onfig\x18\x04 \x01(\x0b\x32 .meshtastic.protobuf.LocalConfigH\x03\x88\x01\x01\x12\x42\n\rmodule_config\x18\x05 \x01(\x0b\x32&.meshtastic.protobuf.LocalModuleConfigH\x04\x88\x01\x01\x12:\n\x0e\x66ixed_position\x18\x06 \x01(\x0b\x32\x1d.meshtastic.protobuf.PositionH\x05\x88\x01\x01\x12\x1d\n\x08ringtone\x18\x07 \x01(\tB\x06\x92?\x03\x08\xe7\x01H\x06\x88\x01\x01\x12$\n\x0f\x63\x61nned_messages\x18\x08 \x01(\tB\x06\x92?\x03\x08\xc9\x01H\x07\x88\x01\x01\x42\x0c\n\n_long_nameB\r\n\x0b_short_nameB\x0e\n\x0c_channel_urlB\t\n\x07_configB\x10\n\x0e_module_configB\x11\n\x0f_fixed_positionB\x0b\n\t_ringtoneB\x12\n\x10_canned_messagesBf\n\x14org.meshtastic.protoB\x10\x43lientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -23,6 +24,14 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.cliento
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\020ClientOnlyProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_DEVICEPROFILE']._serialized_start=131
_globals['_DEVICEPROFILE']._serialized_end=583
_DEVICEPROFILE.fields_by_name['long_name']._options = None
_DEVICEPROFILE.fields_by_name['long_name']._serialized_options = b'\222?\002\010('
_DEVICEPROFILE.fields_by_name['short_name']._options = None
_DEVICEPROFILE.fields_by_name['short_name']._serialized_options = b'\222?\002\010\005'
_DEVICEPROFILE.fields_by_name['ringtone']._options = None
_DEVICEPROFILE.fields_by_name['ringtone']._serialized_options = b'\222?\003\010\347\001'
_DEVICEPROFILE.fields_by_name['canned_messages']._options = None
_DEVICEPROFILE.fields_by_name['canned_messages']._serialized_options = b'\222?\003\010\311\001'
_globals['_DEVICEPROFILE']._serialized_start=165
_globals['_DEVICEPROFILE']._serialized_end=647
# @@protoc_insertion_point(module_scope)

View File

File diff suppressed because one or more lines are too long

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n+meshtastic/protobuf/connection_status.proto\x12\x13meshtastic.protobuf\"\xd5\x02\n\x16\x44\x65viceConnectionStatus\x12<\n\x04wifi\x18\x01 \x01(\x0b\x32).meshtastic.protobuf.WifiConnectionStatusH\x00\x88\x01\x01\x12\x44\n\x08\x65thernet\x18\x02 \x01(\x0b\x32-.meshtastic.protobuf.EthernetConnectionStatusH\x01\x88\x01\x01\x12\x46\n\tbluetooth\x18\x03 \x01(\x0b\x32..meshtastic.protobuf.BluetoothConnectionStatusH\x02\x88\x01\x01\x12@\n\x06serial\x18\x04 \x01(\x0b\x32+.meshtastic.protobuf.SerialConnectionStatusH\x03\x88\x01\x01\x42\x07\n\x05_wifiB\x0b\n\t_ethernetB\x0c\n\n_bluetoothB\t\n\x07_serial\"p\n\x14WifiConnectionStatus\x12<\n\x06status\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.NetworkConnectionStatus\x12\x0c\n\x04ssid\x18\x02 \x01(\t\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\"X\n\x18\x45thernetConnectionStatus\x12<\n\x06status\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.NetworkConnectionStatus\"{\n\x17NetworkConnectionStatus\x12\x12\n\nip_address\x18\x01 \x01(\x07\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x12\x19\n\x11is_mqtt_connected\x18\x03 \x01(\x08\x12\x1b\n\x13is_syslog_connected\x18\x04 \x01(\x08\"L\n\x19\x42luetoothConnectionStatus\x12\x0b\n\x03pin\x18\x01 \x01(\r\x12\x0c\n\x04rssi\x18\x02 \x01(\x05\x12\x14\n\x0cis_connected\x18\x03 \x01(\x08\"<\n\x16SerialConnectionStatus\x12\x0c\n\x04\x62\x61ud\x18\x01 \x01(\r\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x42\x66\n\x14org.meshtastic.protoB\x10\x43onnStatusProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n+meshtastic/protobuf/connection_status.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"\xd5\x02\n\x16\x44\x65viceConnectionStatus\x12<\n\x04wifi\x18\x01 \x01(\x0b\x32).meshtastic.protobuf.WifiConnectionStatusH\x00\x88\x01\x01\x12\x44\n\x08\x65thernet\x18\x02 \x01(\x0b\x32-.meshtastic.protobuf.EthernetConnectionStatusH\x01\x88\x01\x01\x12\x46\n\tbluetooth\x18\x03 \x01(\x0b\x32..meshtastic.protobuf.BluetoothConnectionStatusH\x02\x88\x01\x01\x12@\n\x06serial\x18\x04 \x01(\x0b\x32+.meshtastic.protobuf.SerialConnectionStatusH\x03\x88\x01\x01\x42\x07\n\x05_wifiB\x0b\n\t_ethernetB\x0c\n\n_bluetoothB\t\n\x07_serial\"w\n\x14WifiConnectionStatus\x12<\n\x06status\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.NetworkConnectionStatus\x12\x13\n\x04ssid\x18\x02 \x01(\tB\x05\x92?\x02\x08!\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\"X\n\x18\x45thernetConnectionStatus\x12<\n\x06status\x18\x01 \x01(\x0b\x32,.meshtastic.protobuf.NetworkConnectionStatus\"{\n\x17NetworkConnectionStatus\x12\x12\n\nip_address\x18\x01 \x01(\x07\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x12\x19\n\x11is_mqtt_connected\x18\x03 \x01(\x08\x12\x1b\n\x13is_syslog_connected\x18\x04 \x01(\x08\"L\n\x19\x42luetoothConnectionStatus\x12\x0b\n\x03pin\x18\x01 \x01(\r\x12\x0c\n\x04rssi\x18\x02 \x01(\x05\x12\x14\n\x0cis_connected\x18\x03 \x01(\x08\"<\n\x16SerialConnectionStatus\x12\x0c\n\x04\x62\x61ud\x18\x01 \x01(\r\x12\x14\n\x0cis_connected\x18\x02 \x01(\x08\x42\x66\n\x14org.meshtastic.protoB\x10\x43onnStatusProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,16 +22,18 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.connect
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\020ConnStatusProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_DEVICECONNECTIONSTATUS']._serialized_start=69
_globals['_DEVICECONNECTIONSTATUS']._serialized_end=410
_globals['_WIFICONNECTIONSTATUS']._serialized_start=412
_globals['_WIFICONNECTIONSTATUS']._serialized_end=524
_globals['_ETHERNETCONNECTIONSTATUS']._serialized_start=526
_globals['_ETHERNETCONNECTIONSTATUS']._serialized_end=614
_globals['_NETWORKCONNECTIONSTATUS']._serialized_start=616
_globals['_NETWORKCONNECTIONSTATUS']._serialized_end=739
_globals['_BLUETOOTHCONNECTIONSTATUS']._serialized_start=741
_globals['_BLUETOOTHCONNECTIONSTATUS']._serialized_end=817
_globals['_SERIALCONNECTIONSTATUS']._serialized_start=819
_globals['_SERIALCONNECTIONSTATUS']._serialized_end=879
_WIFICONNECTIONSTATUS.fields_by_name['ssid']._options = None
_WIFICONNECTIONSTATUS.fields_by_name['ssid']._serialized_options = b'\222?\002\010!'
_globals['_DEVICECONNECTIONSTATUS']._serialized_start=103
_globals['_DEVICECONNECTIONSTATUS']._serialized_end=444
_globals['_WIFICONNECTIONSTATUS']._serialized_start=446
_globals['_WIFICONNECTIONSTATUS']._serialized_end=565
_globals['_ETHERNETCONNECTIONSTATUS']._serialized_start=567
_globals['_ETHERNETCONNECTIONSTATUS']._serialized_end=655
_globals['_NETWORKCONNECTIONSTATUS']._serialized_start=657
_globals['_NETWORKCONNECTIONSTATUS']._serialized_end=780
_globals['_BLUETOOTHCONNECTIONSTATUS']._serialized_start=782
_globals['_BLUETOOTHCONNECTIONSTATUS']._serialized_end=858
_globals['_SERIALCONNECTIONSTATUS']._serialized_start=860
_globals['_SERIALCONNECTIONSTATUS']._serialized_end=920
# @@protoc_insertion_point(module_scope)

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#meshtastic/protobuf/device_ui.proto\x12\x13meshtastic.protobuf\"\xff\x05\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\x12K\n\ngps_format\x18\x13 \x01(\x0e\x32\x37.meshtastic.protobuf.DeviceUIConfig.GpsCoordinateFormat\"V\n\x13GpsCoordinateFormat\x12\x07\n\x03\x44\x45\x43\x10\x00\x12\x07\n\x03\x44MS\x10\x01\x12\x07\n\x03UTM\x10\x02\x12\x08\n\x04MGRS\x10\x03\x12\x07\n\x03OLC\x10\x04\x12\x08\n\x04OSGR\x10\x05\x12\x07\n\x03MLS\x10\x06\"\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*\xc0\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\t\n\x05\x43ZECH\x10\x12\x12\n\n\x06\x44\x41NISH\x10\x13\x12\x16\n\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n\x13TRADITIONAL_CHINESE\x10\x1f\x42\x64\n\x14org.meshtastic.protoB\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\x1a meshtastic/protobuf/nanopb.proto\"\xa9\x06\n\x0e\x44\x65viceUIConfig\x12\x0f\n\x07version\x18\x01 \x01(\r\x12 \n\x11screen_brightness\x18\x02 \x01(\rB\x05\x92?\x02\x38\x08\x12\x1d\n\x0escreen_timeout\x18\x03 \x01(\rB\x05\x92?\x02\x38\x10\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\x1b\n\x0cring_tone_id\x18\n \x01(\rB\x05\x92?\x02\x38\x08\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\x1f\n\x10\x63\x61libration_data\x18\x0e \x01(\x0c\x42\x05\x92?\x02\x08\x10\x12*\n\x08map_data\x18\x0f \x01(\x0b\x32\x18.meshtastic.protobuf.Map\x12=\n\x0c\x63ompass_mode\x18\x10 \x01(\x0e\x32 .meshtastic.protobuf.CompassModeB\x05\x92?\x02\x38\x08\x12\x18\n\x10screen_rgb_color\x18\x11 \x01(\r\x12\x1b\n\x13is_clockface_analog\x18\x12 \x01(\x08\x12R\n\ngps_format\x18\x13 \x01(\x0e\x32\x37.meshtastic.protobuf.DeviceUIConfig.GpsCoordinateFormatB\x05\x92?\x02\x38\x08\"V\n\x13GpsCoordinateFormat\x12\x07\n\x03\x44\x45\x43\x10\x00\x12\x07\n\x03\x44MS\x10\x01\x12\x07\n\x03UTM\x10\x02\x12\x08\n\x04MGRS\x10\x03\x12\x07\n\x03OLC\x10\x04\x12\x08\n\x04OSGR\x10\x05\x12\x07\n\x03MLS\x10\x06\"\xbc\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\x18\n\thops_away\x18\x04 \x01(\x05\x42\x05\x92?\x02\x38\x08\x12\x17\n\x0fposition_switch\x18\x05 \x01(\x08\x12\x18\n\tnode_name\x18\x06 \x01(\tB\x05\x92?\x02\x08\x10\x12\x16\n\x07\x63hannel\x18\x07 \x01(\x05\x42\x05\x92?\x02\x38\x08\"\x85\x01\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\x18\n\tnode_name\x18\x05 \x01(\tB\x05\x92?\x02\x08\x10\"D\n\x08GeoPoint\x12\x13\n\x04zoom\x18\x01 \x01(\x05\x42\x05\x92?\x02\x38\x08\x12\x10\n\x08latitude\x18\x02 \x01(\x05\x12\x11\n\tlongitude\x18\x03 \x01(\x05\"\\\n\x03Map\x12+\n\x04home\x18\x01 \x01(\x0b\x32\x1d.meshtastic.protobuf.GeoPoint\x12\x14\n\x05style\x18\x02 \x01(\tB\x05\x92?\x02\x08\x14\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*\xc0\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\t\n\x05\x43ZECH\x10\x12\x12\n\n\x06\x44\x41NISH\x10\x13\x12\x16\n\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n\x13TRADITIONAL_CHINESE\x10\x1f\x42\x64\n\x14org.meshtastic.protoB\x0e\x44\x65viceUIProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,22 +22,46 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.device_
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\016DeviceUIProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_COMPASSMODE']._serialized_start=1278
_globals['_COMPASSMODE']._serialized_end=1340
_globals['_THEME']._serialized_start=1342
_globals['_THEME']._serialized_end=1379
_globals['_LANGUAGE']._serialized_start=1382
_globals['_LANGUAGE']._serialized_end=1702
_globals['_DEVICEUICONFIG']._serialized_start=61
_globals['_DEVICEUICONFIG']._serialized_end=828
_globals['_DEVICEUICONFIG_GPSCOORDINATEFORMAT']._serialized_start=742
_globals['_DEVICEUICONFIG_GPSCOORDINATEFORMAT']._serialized_end=828
_globals['_NODEFILTER']._serialized_start=831
_globals['_NODEFILTER']._serialized_end=998
_globals['_NODEHIGHLIGHT']._serialized_start=1000
_globals['_NODEHIGHLIGHT']._serialized_end=1126
_globals['_GEOPOINT']._serialized_start=1128
_globals['_GEOPOINT']._serialized_end=1189
_globals['_MAP']._serialized_start=1191
_globals['_MAP']._serialized_end=1276
_DEVICEUICONFIG.fields_by_name['screen_brightness']._options = None
_DEVICEUICONFIG.fields_by_name['screen_brightness']._serialized_options = b'\222?\0028\010'
_DEVICEUICONFIG.fields_by_name['screen_timeout']._options = None
_DEVICEUICONFIG.fields_by_name['screen_timeout']._serialized_options = b'\222?\0028\020'
_DEVICEUICONFIG.fields_by_name['ring_tone_id']._options = None
_DEVICEUICONFIG.fields_by_name['ring_tone_id']._serialized_options = b'\222?\0028\010'
_DEVICEUICONFIG.fields_by_name['calibration_data']._options = None
_DEVICEUICONFIG.fields_by_name['calibration_data']._serialized_options = b'\222?\002\010\020'
_DEVICEUICONFIG.fields_by_name['compass_mode']._options = None
_DEVICEUICONFIG.fields_by_name['compass_mode']._serialized_options = b'\222?\0028\010'
_DEVICEUICONFIG.fields_by_name['gps_format']._options = None
_DEVICEUICONFIG.fields_by_name['gps_format']._serialized_options = b'\222?\0028\010'
_NODEFILTER.fields_by_name['hops_away']._options = None
_NODEFILTER.fields_by_name['hops_away']._serialized_options = b'\222?\0028\010'
_NODEFILTER.fields_by_name['node_name']._options = None
_NODEFILTER.fields_by_name['node_name']._serialized_options = b'\222?\002\010\020'
_NODEFILTER.fields_by_name['channel']._options = None
_NODEFILTER.fields_by_name['channel']._serialized_options = b'\222?\0028\010'
_NODEHIGHLIGHT.fields_by_name['node_name']._options = None
_NODEHIGHLIGHT.fields_by_name['node_name']._serialized_options = b'\222?\002\010\020'
_GEOPOINT.fields_by_name['zoom']._options = None
_GEOPOINT.fields_by_name['zoom']._serialized_options = b'\222?\0028\010'
_MAP.fields_by_name['style']._options = None
_MAP.fields_by_name['style']._serialized_options = b'\222?\002\010\024'
_globals['_COMPASSMODE']._serialized_start=1397
_globals['_COMPASSMODE']._serialized_end=1459
_globals['_THEME']._serialized_start=1461
_globals['_THEME']._serialized_end=1498
_globals['_LANGUAGE']._serialized_start=1501
_globals['_LANGUAGE']._serialized_end=1821
_globals['_DEVICEUICONFIG']._serialized_start=95
_globals['_DEVICEUICONFIG']._serialized_end=904
_globals['_DEVICEUICONFIG_GPSCOORDINATEFORMAT']._serialized_start=818
_globals['_DEVICEUICONFIG_GPSCOORDINATEFORMAT']._serialized_end=904
_globals['_NODEFILTER']._serialized_start=907
_globals['_NODEFILTER']._serialized_end=1095
_globals['_NODEHIGHLIGHT']._serialized_start=1098
_globals['_NODEHIGHLIGHT']._serialized_end=1231
_globals['_GEOPOINT']._serialized_start=1233
_globals['_GEOPOINT']._serialized_end=1301
_globals['_MAP']._serialized_start=1303
_globals['_MAP']._serialized_end=1395
# @@protoc_insertion_point(module_scope)

View File

@@ -19,7 +19,7 @@ from meshtastic.protobuf import telemetry_pb2 as meshtastic_dot_protobuf_dot_tel
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 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.UserBn\n\x14org.meshtastic.protoB\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\"\xb0\x02\n\x08UserLite\x12\x1a\n\x07macaddr\x18\x01 \x01(\x0c\x42\t\x18\x01\x92?\x04\x08\x06x\x01\x12\x18\n\tlong_name\x18\x02 \x01(\tB\x05\x92?\x02\x08(\x12\x19\n\nshort_name\x18\x03 \x01(\tB\x05\x92?\x02\x08\x05\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\x19\n\npublic_key\x18\x07 \x01(\x0c\x42\x05\x92?\x02\x08 \x12\x1c\n\x0fis_unmessagable\x18\t \x01(\x08H\x00\x88\x01\x01\x42\x12\n\x10_is_unmessagable\"\x85\x03\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\x16\n\x07\x63hannel\x18\x07 \x01(\rB\x05\x92?\x02\x38\x08\x12\x10\n\x08via_mqtt\x18\x08 \x01(\x08\x12\x1d\n\thops_away\x18\t \x01(\rB\x05\x92?\x02\x38\x08H\x00\x88\x01\x01\x12\x13\n\x0bis_favorite\x18\n \x01(\x08\x12\x12\n\nis_ignored\x18\x0b \x01(\x08\x12\x17\n\x08next_hop\x18\x0c \x01(\rB\x05\x92?\x02\x38\x08\x12\x10\n\x08\x62itfield\x18\r \x01(\rB\x0c\n\n_hops_away\"\xaf\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=\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x1f.meshtastic.protobuf.MeshPacketB\x05\x92?\x02\x10\x01\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\x12T\n\x19node_remote_hardware_pins\x18\r \x03(\x0b\x32*.meshtastic.protobuf.NodeRemoteHardwarePinB\x05\x92?\x02\x10\x0c\"}\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>\"U\n\x0b\x43hannelFile\x12\x35\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1c.meshtastic.protobuf.ChannelB\x05\x92?\x02\x10\x08\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.UserBn\n\x14org.meshtastic.protoB\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)
@@ -28,25 +28,43 @@ if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\nDeviceOnlyZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000\222?\013\302\001\010<vector>'
_USERLITE.fields_by_name['macaddr']._options = None
_USERLITE.fields_by_name['macaddr']._serialized_options = b'\030\001'
_USERLITE.fields_by_name['macaddr']._serialized_options = b'\030\001\222?\004\010\006x\001'
_USERLITE.fields_by_name['long_name']._options = None
_USERLITE.fields_by_name['long_name']._serialized_options = b'\222?\002\010('
_USERLITE.fields_by_name['short_name']._options = None
_USERLITE.fields_by_name['short_name']._serialized_options = b'\222?\002\010\005'
_USERLITE.fields_by_name['public_key']._options = None
_USERLITE.fields_by_name['public_key']._serialized_options = b'\222?\002\010 '
_NODEINFOLITE.fields_by_name['channel']._options = None
_NODEINFOLITE.fields_by_name['channel']._serialized_options = b'\222?\0028\010'
_NODEINFOLITE.fields_by_name['hops_away']._options = None
_NODEINFOLITE.fields_by_name['hops_away']._serialized_options = b'\222?\0028\010'
_NODEINFOLITE.fields_by_name['next_hop']._options = None
_NODEINFOLITE.fields_by_name['next_hop']._serialized_options = b'\222?\0028\010'
_DEVICESTATE.fields_by_name['receive_queue']._options = None
_DEVICESTATE.fields_by_name['receive_queue']._serialized_options = b'\222?\002\020\001'
_DEVICESTATE.fields_by_name['no_save']._options = None
_DEVICESTATE.fields_by_name['no_save']._serialized_options = b'\030\001'
_DEVICESTATE.fields_by_name['did_gps_reset']._options = None
_DEVICESTATE.fields_by_name['did_gps_reset']._serialized_options = b'\030\001'
_DEVICESTATE.fields_by_name['node_remote_hardware_pins']._options = None
_DEVICESTATE.fields_by_name['node_remote_hardware_pins']._serialized_options = b'\222?\002\020\014'
_NODEDATABASE.fields_by_name['nodes']._options = None
_NODEDATABASE.fields_by_name['nodes']._serialized_options = b'\222?\'\222\001$std::vector<meshtastic_NodeInfoLite>'
_CHANNELFILE.fields_by_name['channels']._options = None
_CHANNELFILE.fields_by_name['channels']._serialized_options = b'\222?\002\020\010'
_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
_globals['_USERLITE']._serialized_end=731
_globals['_NODEINFOLITE']._serialized_start=734
_globals['_NODEINFOLITE']._serialized_end=1123
_globals['_DEVICESTATE']._serialized_start=1126
_globals['_DEVICESTATE']._serialized_end=1557
_globals['_NODEDATABASE']._serialized_start=1559
_globals['_NODEDATABASE']._serialized_end=1684
_globals['_CHANNELFILE']._serialized_start=1686
_globals['_CHANNELFILE']._serialized_end=1771
_globals['_BACKUPPREFERENCES']._serialized_start=1774
_globals['_BACKUPPREFERENCES']._serialized_end=2036
# @@protoc_insertion_point(module_scope)

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
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\x42g\n\x14org.meshtastic.protoB\x11InterdeviceProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%meshtastic/protobuf/interdevice.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"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\"g\n\x12InterdeviceMessage\x12\x16\n\x04nmea\x18\x01 \x01(\tB\x06\x92?\x03\x08\x80\x08H\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\x42g\n\x14org.meshtastic.protoB\x11InterdeviceProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,10 +22,12 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.interde
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\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
_INTERDEVICEMESSAGE.fields_by_name['nmea']._options = None
_INTERDEVICEMESSAGE.fields_by_name['nmea']._serialized_options = b'\222?\003\010\200\010'
_globals['_MESSAGETYPE']._serialized_start=319
_globals['_MESSAGETYPE']._serialized_end=532
_globals['_SENSORDATA']._serialized_start=96
_globals['_SENSORDATA']._serialized_end=211
_globals['_INTERDEVICEMESSAGE']._serialized_start=213
_globals['_INTERDEVICEMESSAGE']._serialized_end=316
# @@protoc_insertion_point(module_scope)

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

@@ -13,9 +13,10 @@ _sym_db = _symbol_database.Default()
from meshtastic.protobuf import config_pb2 as meshtastic_dot_protobuf_dot_config__pb2
from meshtastic.protobuf import mesh_pb2 as meshtastic_dot_protobuf_dot_mesh__pb2
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__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\"\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\x14org.meshtastic.protoB\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\x1a meshtastic/protobuf/nanopb.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\"\x9f\x04\n\tMapReport\x12\x18\n\tlong_name\x18\x01 \x01(\tB\x05\x92?\x02\x08(\x12\x19\n\nshort_name\x18\x02 \x01(\tB\x05\x92?\x02\x08\x05\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\x1f\n\x10\x66irmware_version\x18\x05 \x01(\tB\x05\x92?\x02\x08\x12\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%\n\x16num_online_local_nodes\x18\r \x01(\rB\x05\x92?\x02\x38\x10\x12!\n\x19has_opted_report_location\x18\x0e \x01(\x08\x42`\n\x14org.meshtastic.protoB\nMQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -23,8 +24,16 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.mqtt_pb
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\nMQTTProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_SERVICEENVELOPE']._serialized_start=121
_globals['_SERVICEENVELOPE']._serialized_end=227
_globals['_MAPREPORT']._serialized_start=230
_globals['_MAPREPORT']._serialized_end=745
_MAPREPORT.fields_by_name['long_name']._options = None
_MAPREPORT.fields_by_name['long_name']._serialized_options = b'\222?\002\010('
_MAPREPORT.fields_by_name['short_name']._options = None
_MAPREPORT.fields_by_name['short_name']._serialized_options = b'\222?\002\010\005'
_MAPREPORT.fields_by_name['firmware_version']._options = None
_MAPREPORT.fields_by_name['firmware_version']._serialized_options = b'\222?\002\010\022'
_MAPREPORT.fields_by_name['num_online_local_nodes']._options = None
_MAPREPORT.fields_by_name['num_online_local_nodes']._serialized_options = b'\222?\0028\020'
_globals['_SERVICEENVELOPE']._serialized_start=155
_globals['_SERVICEENVELOPE']._serialized_end=261
_globals['_MAPREPORT']._serialized_start=264
_globals['_MAPREPORT']._serialized_end=807
# @@protoc_insertion_point(module_scope)

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/rtttl.proto\x12\x13meshtastic.protobuf\"\x1f\n\x0bRTTTLConfig\x12\x10\n\x08ringtone\x18\x01 \x01(\tBg\n\x14org.meshtastic.protoB\x11RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtastic/protobuf/rtttl.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"\'\n\x0bRTTTLConfig\x12\x18\n\x08ringtone\x18\x01 \x01(\tB\x06\x92?\x03\x08\xe7\x01\x42g\n\x14org.meshtastic.protoB\x11RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,6 +22,8 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.rtttl_p
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\021RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_RTTTLCONFIG']._serialized_start=56
_globals['_RTTTLCONFIG']._serialized_end=87
_RTTTLCONFIG.fields_by_name['ringtone']._options = None
_RTTTLCONFIG.fields_by_name['ringtone']._serialized_options = b'\222?\003\010\347\001'
_globals['_RTTTLCONFIG']._serialized_start=90
_globals['_RTTTLCONFIG']._serialized_end=129
# @@protoc_insertion_point(module_scope)

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/serial_hal.proto\x12\x13meshtastic.protobuf\"\xab\x02\n\x10SerialHalCommand\x12\x16\n\x0etransaction_id\x18\x01 \x01(\r\x12\x38\n\x04type\x18\x02 \x01(\x0e\x32*.meshtastic.protobuf.SerialHalCommand.Type\x12\x0b\n\x03pin\x18\x03 \x01(\r\x12\r\n\x05value\x18\x04 \x01(\r\x12\x0c\n\x04mode\x18\x05 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\"\x8c\x01\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08PIN_MODE\x10\x01\x12\x11\n\rDIGITAL_WRITE\x10\x02\x12\x10\n\x0c\x44IGITAL_READ\x10\x03\x12\x14\n\x10\x41TTACH_INTERRUPT\x10\x04\x12\x14\n\x10\x44\x45TACH_INTERRUPT\x10\x05\x12\x10\n\x0cSPI_TRANSFER\x10\x06\x12\x08\n\x04NOOP\x10\x07\"\xd5\x01\n\x11SerialHalResponse\x12\x16\n\x0etransaction_id\x18\x01 \x01(\r\x12=\n\x06result\x18\x02 \x01(\x0e\x32-.meshtastic.protobuf.SerialHalResponse.Result\x12\r\n\x05value\x18\x03 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\r\n\x05\x65rror\x18\x05 \x01(\t\"=\n\x06Result\x12\x06\n\x02OK\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10\x02\x12\x0f\n\x0bUNSUPPORTED\x10\x03\x42_\n\x14org.meshtastic.protoB\tSerialHalZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtastic/protobuf/serial_hal.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"\xb3\x02\n\x10SerialHalCommand\x12\x16\n\x0etransaction_id\x18\x01 \x01(\r\x12\x38\n\x04type\x18\x02 \x01(\x0e\x32*.meshtastic.protobuf.SerialHalCommand.Type\x12\x0b\n\x03pin\x18\x03 \x01(\r\x12\r\n\x05value\x18\x04 \x01(\r\x12\x0c\n\x04mode\x18\x05 \x01(\r\x12\x14\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x42\x06\x92?\x03\x08\x80\x04\"\x8c\x01\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08PIN_MODE\x10\x01\x12\x11\n\rDIGITAL_WRITE\x10\x02\x12\x10\n\x0c\x44IGITAL_READ\x10\x03\x12\x14\n\x10\x41TTACH_INTERRUPT\x10\x04\x12\x14\n\x10\x44\x45TACH_INTERRUPT\x10\x05\x12\x10\n\x0cSPI_TRANSFER\x10\x06\x12\x08\n\x04NOOP\x10\x07\"\xe4\x01\n\x11SerialHalResponse\x12\x16\n\x0etransaction_id\x18\x01 \x01(\r\x12=\n\x06result\x18\x02 \x01(\x0e\x32-.meshtastic.protobuf.SerialHalResponse.Result\x12\r\n\x05value\x18\x03 \x01(\r\x12\x14\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x42\x06\x92?\x03\x08\x80\x04\x12\x14\n\x05\x65rror\x18\x05 \x01(\tB\x05\x92?\x02\x08P\"=\n\x06Result\x12\x06\n\x02OK\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10\x02\x12\x0f\n\x0bUNSUPPORTED\x10\x03\x42_\n\x14org.meshtastic.protoB\tSerialHalZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,12 +22,18 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.serial_
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\tSerialHalZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_SERIALHALCOMMAND']._serialized_start=62
_globals['_SERIALHALCOMMAND']._serialized_end=361
_globals['_SERIALHALCOMMAND_TYPE']._serialized_start=221
_globals['_SERIALHALCOMMAND_TYPE']._serialized_end=361
_globals['_SERIALHALRESPONSE']._serialized_start=364
_globals['_SERIALHALRESPONSE']._serialized_end=577
_globals['_SERIALHALRESPONSE_RESULT']._serialized_start=516
_globals['_SERIALHALRESPONSE_RESULT']._serialized_end=577
_SERIALHALCOMMAND.fields_by_name['data']._options = None
_SERIALHALCOMMAND.fields_by_name['data']._serialized_options = b'\222?\003\010\200\004'
_SERIALHALRESPONSE.fields_by_name['data']._options = None
_SERIALHALRESPONSE.fields_by_name['data']._serialized_options = b'\222?\003\010\200\004'
_SERIALHALRESPONSE.fields_by_name['error']._options = None
_SERIALHALRESPONSE.fields_by_name['error']._serialized_options = b'\222?\002\010P'
_globals['_SERIALHALCOMMAND']._serialized_start=96
_globals['_SERIALHALCOMMAND']._serialized_end=403
_globals['_SERIALHALCOMMAND_TYPE']._serialized_start=263
_globals['_SERIALHALCOMMAND_TYPE']._serialized_end=403
_globals['_SERIALHALRESPONSE']._serialized_start=406
_globals['_SERIALHALRESPONSE']._serialized_end=634
_globals['_SERIALHALRESPONSE_RESULT']._serialized_start=573
_globals['_SERIALHALRESPONSE_RESULT']._serialized_end=634
# @@protoc_insertion_point(module_scope)

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&meshtastic/protobuf/storeforward.proto\x12\x13meshtastic.protobuf\"\xc0\x07\n\x0fStoreAndForward\x12@\n\x02rr\x18\x01 \x01(\x0e\x32\x34.meshtastic.protobuf.StoreAndForward.RequestResponse\x12@\n\x05stats\x18\x02 \x01(\x0b\x32/.meshtastic.protobuf.StoreAndForward.StatisticsH\x00\x12?\n\x07history\x18\x03 \x01(\x0b\x32,.meshtastic.protobuf.StoreAndForward.HistoryH\x00\x12\x43\n\theartbeat\x18\x04 \x01(\x0b\x32..meshtastic.protobuf.StoreAndForward.HeartbeatH\x00\x12\x0e\n\x04text\x18\x05 \x01(\x0cH\x00\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xbc\x02\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0cROUTER_STATS\x10\x07\x12\x16\n\x12ROUTER_TEXT_DIRECT\x10\x08\x12\x19\n\x15ROUTER_TEXT_BROADCAST\x10\t\x12\x10\n\x0c\x43LIENT_ERROR\x10@\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x41\x12\x10\n\x0c\x43LIENT_STATS\x10\x42\x12\x0f\n\x0b\x43LIENT_PING\x10\x43\x12\x0f\n\x0b\x43LIENT_PONG\x10\x44\x12\x10\n\x0c\x43LIENT_ABORT\x10jB\t\n\x07variantBk\n\x14org.meshtastic.protoB\x15StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&meshtastic/protobuf/storeforward.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"\xc8\x07\n\x0fStoreAndForward\x12@\n\x02rr\x18\x01 \x01(\x0e\x32\x34.meshtastic.protobuf.StoreAndForward.RequestResponse\x12@\n\x05stats\x18\x02 \x01(\x0b\x32/.meshtastic.protobuf.StoreAndForward.StatisticsH\x00\x12?\n\x07history\x18\x03 \x01(\x0b\x32,.meshtastic.protobuf.StoreAndForward.HistoryH\x00\x12\x43\n\theartbeat\x18\x04 \x01(\x0b\x32..meshtastic.protobuf.StoreAndForward.HeartbeatH\x00\x12\x16\n\x04text\x18\x05 \x01(\x0c\x42\x06\x92?\x03\x08\xe9\x01H\x00\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xbc\x02\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0cROUTER_STATS\x10\x07\x12\x16\n\x12ROUTER_TEXT_DIRECT\x10\x08\x12\x19\n\x15ROUTER_TEXT_BROADCAST\x10\t\x12\x10\n\x0c\x43LIENT_ERROR\x10@\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x41\x12\x10\n\x0c\x43LIENT_STATS\x10\x42\x12\x0f\n\x0b\x43LIENT_PING\x10\x43\x12\x0f\n\x0b\x43LIENT_PONG\x10\x44\x12\x10\n\x0c\x43LIENT_ABORT\x10jB\t\n\x07variantBk\n\x14org.meshtastic.protoB\x15StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,14 +22,16 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.storefo
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\025StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_STOREANDFORWARD']._serialized_start=64
_globals['_STOREANDFORWARD']._serialized_end=1024
_globals['_STOREANDFORWARD_STATISTICS']._serialized_start=366
_globals['_STOREANDFORWARD_STATISTICS']._serialized_end=571
_globals['_STOREANDFORWARD_HISTORY']._serialized_start=573
_globals['_STOREANDFORWARD_HISTORY']._serialized_end=646
_globals['_STOREANDFORWARD_HEARTBEAT']._serialized_start=648
_globals['_STOREANDFORWARD_HEARTBEAT']._serialized_end=694
_globals['_STOREANDFORWARD_REQUESTRESPONSE']._serialized_start=697
_globals['_STOREANDFORWARD_REQUESTRESPONSE']._serialized_end=1013
_STOREANDFORWARD.fields_by_name['text']._options = None
_STOREANDFORWARD.fields_by_name['text']._serialized_options = b'\222?\003\010\351\001'
_globals['_STOREANDFORWARD']._serialized_start=98
_globals['_STOREANDFORWARD']._serialized_end=1066
_globals['_STOREANDFORWARD_STATISTICS']._serialized_start=408
_globals['_STOREANDFORWARD_STATISTICS']._serialized_end=613
_globals['_STOREANDFORWARD_HISTORY']._serialized_start=615
_globals['_STOREANDFORWARD_HISTORY']._serialized_end=688
_globals['_STOREANDFORWARD_HEARTBEAT']._serialized_start=690
_globals['_STOREANDFORWARD_HEARTBEAT']._serialized_end=736
_globals['_STOREANDFORWARD_REQUESTRESPONSE']._serialized_start=739
_globals['_STOREANDFORWARD_REQUESTRESPONSE']._serialized_end=1055
# @@protoc_insertion_point(module_scope)

View File

File diff suppressed because one or more lines are too long

View File

@@ -11,9 +11,10 @@ from google.protobuf.internal import builder as _builder
_sym_db = _symbol_database.Default()
from meshtastic.protobuf import nanopb_pb2 as meshtastic_dot_protobuf_dot_nanopb__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/xmodem.proto\x12\x13meshtastic.protobuf\"\xbf\x01\n\x06XModem\x12\x34\n\x07\x63ontrol\x18\x01 \x01(\x0e\x32#.meshtastic.protobuf.XModem.Control\x12\x0b\n\x03seq\x18\x02 \x01(\r\x12\r\n\x05\x63rc16\x18\x03 \x01(\r\x12\x0e\n\x06\x62uffer\x18\x04 \x01(\x0c\"S\n\x07\x43ontrol\x12\x07\n\x03NUL\x10\x00\x12\x07\n\x03SOH\x10\x01\x12\x07\n\x03STX\x10\x02\x12\x07\n\x03\x45OT\x10\x04\x12\x07\n\x03\x41\x43K\x10\x06\x12\x07\n\x03NAK\x10\x15\x12\x07\n\x03\x43\x41N\x10\x18\x12\t\n\x05\x43TRLZ\x10\x1a\x42\x62\n\x14org.meshtastic.protoB\x0cXmodemProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n meshtastic/protobuf/xmodem.proto\x12\x13meshtastic.protobuf\x1a meshtastic/protobuf/nanopb.proto\"\xd5\x01\n\x06XModem\x12\x34\n\x07\x63ontrol\x18\x01 \x01(\x0e\x32#.meshtastic.protobuf.XModem.Control\x12\x12\n\x03seq\x18\x02 \x01(\rB\x05\x92?\x02\x38\x10\x12\x14\n\x05\x63rc16\x18\x03 \x01(\rB\x05\x92?\x02\x38\x10\x12\x16\n\x06\x62uffer\x18\x04 \x01(\x0c\x42\x06\x92?\x03\x08\x80\x01\"S\n\x07\x43ontrol\x12\x07\n\x03NUL\x10\x00\x12\x07\n\x03SOH\x10\x01\x12\x07\n\x03STX\x10\x02\x12\x07\n\x03\x45OT\x10\x04\x12\x07\n\x03\x41\x43K\x10\x06\x12\x07\n\x03NAK\x10\x15\x12\x07\n\x03\x43\x41N\x10\x18\x12\t\n\x05\x43TRLZ\x10\x1a\x42\x62\n\x14org.meshtastic.protoB\x0cXmodemProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -21,8 +22,14 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtastic.protobuf.xmodem_
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\024org.meshtastic.protoB\014XmodemProtosZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000'
_globals['_XMODEM']._serialized_start=58
_globals['_XMODEM']._serialized_end=249
_globals['_XMODEM_CONTROL']._serialized_start=166
_globals['_XMODEM_CONTROL']._serialized_end=249
_XMODEM.fields_by_name['seq']._options = None
_XMODEM.fields_by_name['seq']._serialized_options = b'\222?\0028\020'
_XMODEM.fields_by_name['crc16']._options = None
_XMODEM.fields_by_name['crc16']._serialized_options = b'\222?\0028\020'
_XMODEM.fields_by_name['buffer']._options = None
_XMODEM.fields_by_name['buffer']._serialized_options = b'\222?\003\010\200\001'
_globals['_XMODEM']._serialized_start=92
_globals['_XMODEM']._serialized_end=305
_globals['_XMODEM_CONTROL']._serialized_start=222
_globals['_XMODEM_CONTROL']._serialized_end=305
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,646 @@
"""Tests for bin/inject_nanopb_options.py — the nanopb options injection script
and the generated protobuf descriptors it produces.
Part 1 (test_parse_*, test_inject_*): unit-tests the script's logic directly,
using small synthetic proto snippets.
Part 2 (test_descriptor_*): smoke-tests the already-generated _pb2.py files to
confirm the regen pipeline embedded the expected nanopb options.
"""
import importlib.util
import sys
import textwrap
from pathlib import Path
from unittest.mock import patch
import pytest
from hypothesis import given, strategies as st
from meshtastic.protobuf import (
atak_pb2,
config_pb2,
mesh_pb2,
nanopb_pb2,
telemetry_pb2,
)
# ---------------------------------------------------------------------------
# Load bin/inject_nanopb_options.py as a module without adding it to the
# package. __main__ guard means no side-effects on import.
# ---------------------------------------------------------------------------
_SCRIPT_PATH = Path(__file__).parent.parent.parent / "bin" / "inject_nanopb_options.py"
def _load_inject_module():
spec = importlib.util.spec_from_file_location("inject_nanopb_options", _SCRIPT_PATH)
mod = importlib.util.module_from_spec(spec)
with patch.object(sys, "argv", ["inject_nanopb_options.py"]):
spec.loader.exec_module(mod)
return mod
_inj = _load_inject_module()
parse_value = _inj.parse_value
parse_options_file = _inj.parse_options_file
format_nanopb_opts = _inj.format_nanopb_opts
inject_into_proto = _inj.inject_into_proto
message_path_matches = _inj.message_path_matches
# Convenience: the nanopb import path the script uses after the sed fixup
NANOPB_IMPORT = 'import "meshtastic/protobuf/nanopb.proto";'
# ===========================================================================
# Part 1 — Script unit tests
# ===========================================================================
# ---------------------------------------------------------------------------
# parse_value
# ---------------------------------------------------------------------------
@pytest.mark.unit
def test_parse_value_integer():
"""parse_value converts a decimal string to int."""
assert parse_value("40") == 40
@pytest.mark.unit
def test_parse_value_negative_integer():
"""parse_value handles negative integer strings."""
assert parse_value("-1") == -1
@pytest.mark.unit
def test_parse_value_true():
"""parse_value converts 'true' to Python True."""
assert parse_value("true") is True
@pytest.mark.unit
def test_parse_value_false():
"""parse_value converts 'false' to Python False."""
assert parse_value("false") is False
@pytest.mark.unit
def test_parse_value_string():
"""parse_value returns non-numeric, non-boolean strings as-is."""
assert parse_value("IS_8") == "IS_8"
@pytest.mark.unit
@given(st.integers())
def test_parse_value_any_integer_returns_int(n):
"""parse_value always returns int for any decimal integer string."""
assert parse_value(str(n)) == n
@pytest.mark.unit
@given(st.text())
def test_parse_value_never_crashes(s):
"""parse_value never raises on arbitrary input."""
result = parse_value(s)
assert isinstance(result, (int, bool, str))
@pytest.mark.unit
@given(st.text().filter(lambda s: not s.lstrip("-").isdigit() and s.lower() not in ("true", "false")))
def test_parse_value_non_numeric_non_bool_returns_str(s):
"""parse_value returns the original string when it is neither an integer nor a boolean."""
assert parse_value(s) == s
# ---------------------------------------------------------------------------
# parse_options_file
# ---------------------------------------------------------------------------
def _write_options(tmp_path: Path, content: str) -> Path:
p = tmp_path / "test.options"
p.write_text(textwrap.dedent(content))
return p
@pytest.mark.unit
def test_parse_wildcard(tmp_path):
"""Wildcard pattern (no dot) lands in the wildcard dict."""
f = _write_options(tmp_path, "*macaddr max_size:6 fixed_length:true\n")
specific, wildcard = parse_options_file(f)
assert "macaddr" in wildcard
assert wildcard["macaddr"] == {"max_size": 6, "fixed_length": True}
assert specific == {}
@pytest.mark.unit
def test_parse_specific(tmp_path):
"""Single-dot pattern lands in the specific dict with a 2-tuple key."""
f = _write_options(tmp_path, "*User.long_name max_size:40\n")
specific, wildcard = parse_options_file(f)
assert ("User", "long_name") in specific
assert specific[("User", "long_name")] == {"max_size": 40}
assert wildcard == {}
@pytest.mark.unit
def test_parse_multilevel(tmp_path):
"""Three-part pattern (Route.Link.uid) produces a 3-tuple key."""
f = _write_options(tmp_path, "*Route.Link.uid max_size:48\n")
specific, _ = parse_options_file(f)
assert ("Route", "Link", "uid") in specific
assert specific[("Route", "Link", "uid")] == {"max_size": 48}
@pytest.mark.unit
def test_parse_strips_inline_comments(tmp_path):
"""Text after # is ignored."""
f = _write_options(tmp_path, "*id max_size:16 # node id strings\n")
_, wildcard = parse_options_file(f)
assert wildcard["id"] == {"max_size": 16}
@pytest.mark.unit
def test_parse_skips_comment_only_lines(tmp_path):
"""Lines that are entirely comments produce no entries."""
f = _write_options(tmp_path, "# this is a comment\n*id max_size:16\n")
_, wildcard = parse_options_file(f)
assert list(wildcard.keys()) == ["id"]
@pytest.mark.unit
def test_parse_skips_blank_lines(tmp_path):
"""Blank lines are silently ignored."""
f = _write_options(tmp_path, "\n\n*id max_size:16\n\n")
_, wildcard = parse_options_file(f)
assert "id" in wildcard
@pytest.mark.unit
def test_parse_skips_non_python_options(tmp_path):
"""Options not in FIELD_OPTIONS (e.g. anonymous_oneof) are dropped."""
f = _write_options(tmp_path, "*MeshPacket.payload_variant anonymous_oneof:true\n")
specific, wildcard = parse_options_file(f)
# anonymous_oneof is not in FIELD_OPTIONS → no entry should be produced
assert specific == {}
assert wildcard == {}
@pytest.mark.unit
def test_parse_merges_repeated_patterns(tmp_path):
"""Two lines for the same pattern are merged."""
f = _write_options(
tmp_path,
"*SecurityConfig.admin_key max_size:32\n"
"*SecurityConfig.admin_key max_count:3\n",
)
specific, _ = parse_options_file(f)
assert specific[("SecurityConfig", "admin_key")] == {"max_size": 32, "max_count": 3}
@pytest.mark.unit
def test_parse_int_and_bool_values(tmp_path):
"""int_size parses as int; fixed_length parses as bool."""
f = _write_options(tmp_path, "*Data.payload max_size:233 fixed_length:false\n")
specific, _ = parse_options_file(f)
opts = specific[("Data", "payload")]
assert opts["max_size"] == 233
assert opts["fixed_length"] is False
# ---------------------------------------------------------------------------
# message_path_matches
# ---------------------------------------------------------------------------
@pytest.mark.unit
def test_message_path_matches_simple():
"""A single-element path matches the current message on the stack."""
stack = [("message", "User")]
assert message_path_matches(stack, ("User",))
@pytest.mark.unit
def test_message_path_matches_nested():
"""Both a 1-element and 2-element path match correctly against a nested stack."""
stack = [("message", "Config"), ("message", "DeviceConfig")]
assert message_path_matches(stack, ("DeviceConfig",))
assert message_path_matches(stack, ("Config", "DeviceConfig"))
@pytest.mark.unit
def test_message_path_matches_with_oneof_in_stack():
"""oneof frames in the stack are skipped when looking for messages."""
stack = [("message", "MeshPacket"), ("oneof", "payload_variant")]
assert message_path_matches(stack, ("MeshPacket",))
@pytest.mark.unit
def test_message_path_no_match():
"""A path with the wrong message name does not match."""
stack = [("message", "User")]
assert not message_path_matches(stack, ("Route",))
@pytest.mark.unit
def test_message_path_multilevel_partial_match():
"""A 2-element path must match the last 2 message names on the stack."""
stack = [("message", "Route"), ("message", "Link")]
assert message_path_matches(stack, ("Route", "Link"))
assert not message_path_matches(stack, ("Other", "Link"))
# ---------------------------------------------------------------------------
# format_nanopb_opts
# ---------------------------------------------------------------------------
@pytest.mark.unit
def test_format_max_size():
"""max_size is rendered as an integer literal."""
assert format_nanopb_opts({"max_size": 40}) == "(nanopb).max_size = 40"
@pytest.mark.unit
def test_format_int_size_as_enum():
"""int_size numeric values are rendered as IS_8/IS_16/IS_32/IS_64 enum names."""
assert format_nanopb_opts({"int_size": 8}) == "(nanopb).int_size = IS_8"
assert format_nanopb_opts({"int_size": 16}) == "(nanopb).int_size = IS_16"
assert format_nanopb_opts({"int_size": 32}) == "(nanopb).int_size = IS_32"
assert format_nanopb_opts({"int_size": 64}) == "(nanopb).int_size = IS_64"
@pytest.mark.unit
def test_format_bool_true():
"""True is rendered as the proto literal 'true'."""
assert format_nanopb_opts({"fixed_length": True}) == "(nanopb).fixed_length = true"
@pytest.mark.unit
def test_format_bool_false():
"""False is rendered as the proto literal 'false'."""
assert format_nanopb_opts({"fixed_length": False}) == "(nanopb).fixed_length = false"
# ---------------------------------------------------------------------------
# inject_into_proto — helpers
# ---------------------------------------------------------------------------
_NANOPB_IMPORT_PATH = "meshtastic/protobuf/nanopb.proto"
def _inject(proto_src: str, specific=None, wildcard=None) -> str:
"""Run inject_into_proto with empty dicts as defaults."""
return inject_into_proto(
textwrap.dedent(proto_src),
specific or {},
wildcard or {},
_NANOPB_IMPORT_PATH,
)
# ---------------------------------------------------------------------------
# inject_into_proto — option injection
# ---------------------------------------------------------------------------
@pytest.mark.unit
def test_inject_adds_option_to_plain_field():
"""A field with no existing options gets a nanopb annotation."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/channel.proto";
message User {
string long_name = 1;
}
"""
result = _inject(proto, specific={("User", "long_name"): {"max_size": 40}})
assert "long_name = 1 [(nanopb).max_size = 40];" in result
@pytest.mark.unit
def test_inject_merges_with_existing_options():
"""nanopb annotation is appended after existing field options."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/channel.proto";
message User {
bytes macaddr = 4 [deprecated = true];
}
"""
result = _inject(proto, wildcard={"macaddr": {"max_size": 6}})
assert "[deprecated = true, (nanopb).max_size = 6];" in result
@pytest.mark.unit
def test_inject_int_size_uses_enum_name():
"""int_size values are written as IS_N enum names, not raw integers."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Foo {
uint32 hop_limit = 9;
}
"""
result = _inject(proto, specific={("Foo", "hop_limit"): {"int_size": 8}})
assert "(nanopb).int_size = IS_8" in result
@pytest.mark.unit
def test_inject_wildcard_applied_across_messages():
"""A wildcard option hits the matching field in every message."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message A {
bytes macaddr = 1;
}
message B {
bytes macaddr = 2;
}
"""
result = _inject(proto, wildcard={"macaddr": {"max_size": 6}})
assert result.count("(nanopb).max_size = 6") == 2
@pytest.mark.unit
def test_inject_specific_not_leaking_to_other_messages():
"""A message-specific option does NOT apply to a different message's field."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message User {
string id = 1;
}
message Other {
string id = 1;
}
"""
result = _inject(proto, specific={("User", "id"): {"max_size": 16}})
# Easier: count annotations — should be exactly one
assert result.count("(nanopb).max_size = 16") == 1
@pytest.mark.unit
def test_inject_nested_message():
"""A 2-part specific key only hits the field in the correct nested message."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Route {
message Link {
string uid = 1;
}
string uid = 2;
}
"""
# Route.Link.uid → key = ('Route', 'Link', 'uid')
result = _inject(proto, specific={("Route", "Link", "uid"): {"max_size": 48}})
lines = result.splitlines()
# Only the uid inside Link should have the annotation
assert result.count("(nanopb).max_size = 48") == 1
# Confirm it's the inner one (it has 4 spaces more indent than outer uid)
annotated = next(l for l in lines if "(nanopb).max_size = 48" in l)
plain = next(l for l in lines if "uid = 2" in l)
assert annotated.index("uid") > plain.index("uid")
@pytest.mark.unit
def test_inject_skips_enum_body_values():
"""Enum value lines must not be treated as field declarations."""
proto = """\
syntax = "proto3";
message Foo {
enum Role {
CLIENT = 0;
ROUTER = 2;
}
Role role = 1;
}
"""
# Wildcard for 'role' should only hit the field, not enum values
result = _inject(proto, wildcard={"role": {"max_size": 8}})
assert result.count("(nanopb)") == 1
assert "(nanopb)" not in next(l for l in result.splitlines() if "CLIENT" in l)
@pytest.mark.unit
def test_inject_optional_qualifier_preserved():
"""The 'optional' qualifier is kept when a field gets an annotation."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Foo {
optional uint32 altitude = 3;
}
"""
result = _inject(proto, specific={("Foo", "altitude"): {"int_size": 16}})
assert "optional uint32 altitude = 3 [(nanopb).int_size = IS_16];" in result
@pytest.mark.unit
def test_inject_repeated_qualifier_preserved():
"""The 'repeated' qualifier is kept when a field gets an annotation."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Foo {
repeated int32 snr = 2;
}
"""
result = _inject(proto, specific={("Foo", "snr"): {"max_count": 8}})
assert "repeated int32 snr = 2 [(nanopb).max_count = 8];" in result
@pytest.mark.unit
def test_inject_multiple_options_on_one_field():
"""Multiple options from the same pattern are all injected on one field."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Foo {
repeated int32 snr = 1;
}
"""
result = _inject(proto, specific={("Foo", "snr"): {"max_count": 8, "int_size": 8}})
assert "(nanopb).max_count = 8" in result
assert "(nanopb).int_size = IS_8" in result
# ---------------------------------------------------------------------------
# inject_into_proto — import insertion
# ---------------------------------------------------------------------------
@pytest.mark.unit
def test_inject_adds_nanopb_import_when_absent():
"""nanopb.proto import is added when the file has other imports."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Foo {
string name = 1;
}
"""
result = _inject(proto, wildcard={"name": {"max_size": 30}})
assert NANOPB_IMPORT in result
@pytest.mark.unit
def test_inject_no_duplicate_nanopb_import():
"""nanopb.proto import is NOT added a second time if already present."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
import "meshtastic/protobuf/nanopb.proto";
message Foo {
string name = 1;
}
"""
result = _inject(proto, wildcard={"name": {"max_size": 30}})
assert result.count(NANOPB_IMPORT) == 1
@pytest.mark.unit
def test_inject_import_placed_after_existing_imports():
"""nanopb import appears after the last existing import, not at the top."""
proto = """\
syntax = "proto3";
import "meshtastic/protobuf/mesh.proto";
message Foo {
string name = 1;
}
"""
result = _inject(proto, wildcard={"name": {"max_size": 30}})
lines = result.splitlines()
mesh_idx = next(i for i, l in enumerate(lines) if "mesh.proto" in l)
nanopb_idx = next(i for i, l in enumerate(lines) if "nanopb.proto" in l)
assert nanopb_idx == mesh_idx + 1
@pytest.mark.unit
def test_inject_import_after_syntax_when_no_existing_imports():
"""When a proto has no imports, nanopb import goes AFTER the syntax line,
not before it (regression test for the last_import_idx == -1 bug)."""
proto = """\
syntax = "proto3";
message XModem {
uint32 seq = 2;
}
"""
result = _inject(proto, specific={("XModem", "seq"): {"int_size": 16}})
lines = result.splitlines()
syntax_idx = next(i for i, l in enumerate(lines) if l.strip().startswith("syntax"))
nanopb_idx = next(i for i, l in enumerate(lines) if "nanopb.proto" in l)
assert nanopb_idx > syntax_idx, "nanopb import must come after the syntax line"
# syntax line must still be first non-blank line
first_non_blank = next(l.strip() for l in lines if l.strip())
assert first_non_blank.startswith("syntax")
@pytest.mark.unit
def test_inject_noop_when_no_options():
"""Proto file is returned unchanged when there are no options to inject."""
proto = 'syntax = "proto3";\nmessage Foo { string x = 1; }\n'
result = _inject(proto)
assert result == proto
# ===========================================================================
# Part 2 — Descriptor integration tests
# Verify that regen-protobufs.sh produced _pb2.py files with nanopb options
# embedded in the serialized descriptors.
# ===========================================================================
def _field_opts(descriptor, *path):
"""Walk a descriptor by field/nested-type path and return its nanopb opts.
Elements of *path that are message names are looked up in nested_types_by_name;
the final element is looked up in fields_by_name.
"""
desc = descriptor
for step in path[:-1]:
desc = desc.nested_types_by_name[step]
field = desc.fields_by_name[path[-1]]
return field.GetOptions().Extensions[nanopb_pb2.nanopb]
@pytest.mark.unit
def test_descriptor_user_long_name():
"""User.long_name has max_size = 40 from mesh.options."""
opts = _field_opts(mesh_pb2.DESCRIPTOR.message_types_by_name["User"], "long_name")
assert opts.max_size == 40
@pytest.mark.unit
def test_descriptor_user_short_name():
"""User.short_name has max_size = 5 from mesh.options."""
opts = _field_opts(mesh_pb2.DESCRIPTOR.message_types_by_name["User"], "short_name")
assert opts.max_size == 5
@pytest.mark.unit
def test_descriptor_wildcard_macaddr():
"""Wildcard option from mesh.options applied to User.macaddr."""
opts = _field_opts(mesh_pb2.DESCRIPTOR.message_types_by_name["User"], "macaddr")
assert opts.max_size == 6
assert opts.fixed_length is True
@pytest.mark.unit
def test_descriptor_meshpacket_hop_limit():
"""MeshPacket.hop_limit has int_size = IS_8 from mesh.options."""
opts = _field_opts(mesh_pb2.DESCRIPTOR.message_types_by_name["MeshPacket"], "hop_limit")
assert opts.int_size == nanopb_pb2.IS_8
@pytest.mark.unit
def test_descriptor_routediscovery_snr_towards():
"""RouteDiscovery.snr_towards has max_count = 8 and int_size = IS_8 from mesh.options."""
opts = _field_opts(
mesh_pb2.DESCRIPTOR.message_types_by_name["RouteDiscovery"], "snr_towards"
)
assert opts.max_count == 8
assert opts.int_size == nanopb_pb2.IS_8
@pytest.mark.unit
def test_descriptor_data_payload():
"""Data.payload has max_size = 233 from mesh.options."""
opts = _field_opts(mesh_pb2.DESCRIPTOR.message_types_by_name["Data"], "payload")
assert opts.max_size == 233
@pytest.mark.unit
def test_descriptor_nested_deviceconfig_tzdef():
"""Config.DeviceConfig.tzdef — option on a field inside a nested message."""
config = config_pb2.DESCRIPTOR.message_types_by_name["Config"]
opts = _field_opts(config, "DeviceConfig", "tzdef")
assert opts.max_size == 65
@pytest.mark.unit
def test_descriptor_nested_securityconfig_admin_key():
"""Config.SecurityConfig.admin_key — two options merged from two .options lines."""
config = config_pb2.DESCRIPTOR.message_types_by_name["Config"]
opts = _field_opts(config, "SecurityConfig", "admin_key")
assert opts.max_size == 32
assert opts.max_count == 3
@pytest.mark.unit
def test_descriptor_multilevel_nested_route_link_uid():
"""Route.Link.uid — three-level nested pattern from atak.options."""
route = atak_pb2.DESCRIPTOR.message_types_by_name["Route"]
opts = _field_opts(route, "Link", "uid")
assert opts.max_size == 48
@pytest.mark.unit
def test_descriptor_telemetry_environment_one_wire_temperature():
"""EnvironmentMetrics.one_wire_temperature has max_count = 8 from telemetry.options."""
env = telemetry_pb2.DESCRIPTOR.message_types_by_name["EnvironmentMetrics"]
opts = _field_opts(env, "one_wire_temperature")
assert opts.max_count == 8