Files
web/packages/protobufs/meshtastic/deviceonly.proto
Ben Meadors bbe9a0d5cd feat(protobufs): sync to firmware-current and consume workspace package (#1097)
* feat(protobufs): sync to firmware-current and consume workspace package

Sync the vendored .proto sources to firmware-current (v2.7.25+48), regenerate the v2 TS bindings, and consume the workspace @meshtastic/protobufs (workspace:*) in place of the stale JSR 2.7.20 — finishing the monorepo migration (core was already workspace:*).

Includes the one required breaking-change fix: admin nodedb_reset changed int32 to bool, so resetNodes() now sends value: true.

* build(protobufs): vendor generated bindings for workspace consumers

The package is consumed via workspace:* — its exports point at the TS source, which imports ./dist/meshtastic/*_pb.ts — so the generated output must exist at build time. CI builds web/core with no codegen step and the runners have no buf CLI, so the bindings are vendored here (kept gitignored; lint/format skip them). Regenerate with: pnpm --filter @meshtastic/protobufs gen

* fix(protobufs): clean script removes the actual generated output dir

buf writes bindings to packages/ts/dist, but clean was removing a non-existent root dist — so it never cleaned stale output. Addresses Copilot review feedback.

* refactor: move web app packages/web -> apps/web

Aligns the web app with the apps/web layout (matching the Vercel web-test Root Directory and the SDK-migration direction). Pure directory move plus root config: pnpm-workspace (adds apps/*), vitest projects, root tsconfig reference, and the pr/release-web/nightly workflows. vercel.json moved with the app. Build + 36 validation tests green.

* feat: config fields, module pages, key verification, telemetry capture

Incorporates the firmware-current feature work onto the protobuf foundation: new config fields (Display message bubbles; LoRa fem_lna_mode + serial_hal_only; Telemetry air_quality_screen_enabled); 4 new ModuleConfig pages (TrafficManagement, StatusMessage, TAK, RemoteHardware); the manual Key Verification flow (sendKeyVerification + ClientNotificationDialog stages + Verify Key button); live telemetry capture (nodeDB addDeviceMetrics) and admin hardening (toggleMutedNode, graceful PortNum default); plus the sdk-preview ConfigEditor demo and store/config tests. Build + lint + format + 131 tests green.

* chore: drop #1062 (unsaved-change-detection) to match upstream revert

#1062 was merged to main by accident (per @danditomaso) and is being reverted. Reverse-applied its diff here via 3-way so #1097 stays consistent with where main is headed, while keeping the feature changes layered on the same files (deviceStore/changeRegistry). Build + 131 tests + lint + format green.

* fix(nodes): clean up SNR display in node table and map popup

SNR is a ratio measured in dB, not dBm (which is absolute power); the
node table and map popup both mislabeled it and crammed three values
together: '0dBm/50%/50raw'. The trailing '%/raw' pair was the same
heuristic ((snr+10)*5) shown twice — once clamped, once not.

Render SNR in dB rounded to one decimal, color-coded by a 0-100%
signal-quality heuristic (green/yellow/red), with the quality percentage
as a muted secondary. Drop the redundant raw value. Adds unit.db; this
matches the existing SNRTooltip, which already renders dB.
2026-06-15 13:23:28 -05:00

354 lines
8.7 KiB
Protocol Buffer
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
syntax = "proto3";
package meshtastic;
/* trunk-ignore(buf-lint/COMPILE) */
import "meshtastic/channel.proto";
import "meshtastic/config.proto";
import "meshtastic/localonly.proto";
import "meshtastic/mesh.proto";
import "meshtastic/telemetry.proto";
import "nanopb.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option java_outer_classname = "DeviceOnly";
option java_package = "org.meshtastic.proto";
option swift_prefix = "";
option (nanopb_fileopt).include = "<vector>";
/*
* Position with static location information only for NodeDBLite
*/
message PositionLite {
/*
* The new preferred location encoding, multiply by 1e-7 to get degrees
* in floating point
*/
sfixed32 latitude_i = 1;
/*
* TODO: REPLACE
*/
sfixed32 longitude_i = 2;
/*
* In meters above MSL (but see issue #359)
*/
int32 altitude = 3;
/*
* This is usually not sent over the mesh (to save space), but it is sent
* from the phone so that the local device can set its RTC If it is sent over
* the mesh (because there are devices on the mesh without GPS), it will only
* be sent by devices which has a hardware GPS clock.
* seconds since 1970
*/
fixed32 time = 4;
/*
* TODO: REPLACE
*/
Position.LocSource location_source = 5;
/*
* Indicates the bits of precision set by the sending node
*/
uint32 precision_bits = 6;
}
message UserLite {
/*
* This is the addr of the radio.
*/
bytes macaddr = 1 [deprecated = true];
/*
* A full name for this user, i.e. "Kevin Hester"
*/
string long_name = 2;
/*
* A VERY short name, ideally two characters.
* Suitable for a tiny OLED screen
*/
string short_name = 3;
/*
* TBEAM, HELTEC, etc...
* Starting in 1.2.11 moved to hw_model enum in the NodeInfo object.
* Apps will still need the string here for older builds
* (so OTA update can find the right image), but if the enum is available it will be used instead.
*/
HardwareModel hw_model = 4;
/*
* In some regions Ham radio operators have different bandwidth limitations than others.
* If this user is a licensed operator, set this flag.
* Also, "long_name" should be their licence number.
*/
bool is_licensed = 5;
/*
* Indicates that the user's role in the mesh
*/
Config.DeviceConfig.Role role = 6;
/*
* The public key of the user's device.
* This is sent out to other nodes on the mesh to allow them to compute a shared secret key.
*/
bytes public_key = 7;
/*
* Whether or not the node can be messaged
*/
optional bool is_unmessagable = 9;
}
message NodeInfoLite {
/*
* The node number
*/
uint32 num = 1;
// Tag 2 was UserLite user; flattened into tags 14..18 (presence via
// NODEINFO_BITFIELD_HAS_USER).
// Tag 3 was PositionLite position; moved to NodeDatabase.positions.
reserved 2, 3;
reserved "user", "position";
/*
* In-memory SNR of the last received message in dB. Not serialised directly:
* always zeroed before encode; persisted as snr_q4 = 19 below.
*/
float snr = 4;
/*
* Set to indicate the last time we received a packet from this node
*/
fixed32 last_heard = 5;
// Tag 6 was DeviceMetrics device_metrics; moved to NodeDatabase.telemetry.
reserved 6;
reserved "device_metrics";
/*
* local channel index we heard that node on. Only populated if its not the default channel.
*/
uint32 channel = 7;
// Tags 8/10/11 were via_mqtt/is_favorite/is_ignored bools; packed into bitfield.
reserved 8, 10, 11;
reserved "via_mqtt", "is_favorite", "is_ignored";
/*
* Number of hops away from us this node is (0 if direct neighbor)
*/
optional uint32 hops_away = 9;
/*
* Last byte of the node number of the node that should be used as the next hop to reach this node.
*/
uint32 next_hop = 12;
/*
* Bitfield for storing booleans. See NODEINFO_BITFIELD_* in src/mesh/NodeDB.h.
*/
uint32 bitfield = 13;
// Flattened user fields (formerly UserLite). macaddr dropped (deprecated 1.2.11).
/*
* A full name for this user, i.e. "Kevin Hester".
*/
string long_name = 14;
/*
* A VERY short name, ideally two characters or an emoji.
* Suitable for a tiny OLED screen.
*/
string short_name = 15;
/*
* Hardware model the user's device is running.
*/
HardwareModel hw_model = 16;
/*
* The user's role in the mesh.
*/
Config.DeviceConfig.Role role = 17;
/*
* The public key of the user's device, for PKI-based encrypted DMs.
*/
bytes public_key = 18;
/*
* Q4-encoded SNR: dB × 4, sint32 zigzag. Matches RouteDiscovery convention.
* Encode: snr_q4 = (int32_t)(snr * 4.0f). Decode: snr = snr_q4 / 4.0f.
* float snr is always zeroed on disk; this field carries all persisted SNR.
*/
sint32 snr_q4 = 19;
}
/*
* This message is never sent over the wire, but it is used for serializing DB
* state to flash in the device code
* FIXME, since we write this each time we enter deep sleep (and have infinite
* flash) it would be better to use some sort of append only data structure for
* the receive queue and use the preferences store for the other stuff
*/
message DeviceState {
/*
* Read only settings/info about this node
*/
MyNodeInfo my_node = 2;
/*
* My owner info
*/
User owner = 3;
/*
* Received packets saved for delivery to the phone
*/
repeated MeshPacket receive_queue = 5;
/*
* A version integer used to invalidate old save files when we make
* incompatible changes This integer is set at build time and is private to
* NodeDB.cpp in the device code.
*/
uint32 version = 8;
/*
* We keep the last received text message (only) stored in the device flash,
* so we can show it on the screen.
* Might be null
*/
MeshPacket rx_text_message = 7;
/*
* Used only during development.
* Indicates developer is testing and changes should never be saved to flash.
* Deprecated in 2.3.1
*/
bool no_save = 9 [deprecated = true];
/*
* Previously used to manage GPS factory resets.
* Deprecated in 2.5.23
*/
bool did_gps_reset = 11 [deprecated = true];
/*
* We keep the last received waypoint stored in the device flash,
* so we can show it on the screen.
* Might be null
*/
MeshPacket rx_waypoint = 12;
/*
* The mesh's nodes with their available gpio pins for RemoteHardware module
*/
repeated NodeRemoteHardwarePin node_remote_hardware_pins = 13;
}
// Satellite per-node entries; stored alongside the slim NodeInfoLite so nodes
// that never report don't pay the embedded cost.
message NodePositionEntry {
uint32 num = 1;
PositionLite position = 2;
}
message NodeTelemetryEntry {
uint32 num = 1;
DeviceMetrics device_metrics = 2;
}
message NodeEnvironmentEntry {
uint32 num = 1;
EnvironmentMetrics environment_metrics = 2;
}
message NodeStatusEntry {
uint32 num = 1;
StatusMessage status = 2;
}
message NodeDatabase {
/*
* A version integer used to invalidate old save files when we make
* incompatible changes This integer is set at build time and is private to
* NodeDB.cpp in the device code.
*/
uint32 version = 1;
/*
* New lite version of NodeDB to decrease memory footprint
*/
repeated NodeInfoLite nodes = 2 [(nanopb).callback_datatype = "std::vector<meshtastic_NodeInfoLite>"];
// Per-NodeNum satellite arrays. Constrained platforms (e.g. STM32WL) omit
// these via MESHTASTIC_EXCLUDE_*DB build flags.
repeated NodePositionEntry positions = 3 [(nanopb).callback_datatype = "std::vector<meshtastic_NodePositionEntry>"];
repeated NodeTelemetryEntry telemetry = 4 [(nanopb).callback_datatype = "std::vector<meshtastic_NodeTelemetryEntry>"];
repeated NodeStatusEntry status = 5 [(nanopb).callback_datatype = "std::vector<meshtastic_NodeStatusEntry>"];
repeated NodeEnvironmentEntry environment = 6 [(nanopb).callback_datatype = "std::vector<meshtastic_NodeEnvironmentEntry>"];
}
/*
* The on-disk saved channels
*/
message ChannelFile {
/*
* The channels our node knows about
*/
repeated Channel channels = 1;
/*
* A version integer used to invalidate old save files when we make
* incompatible changes This integer is set at build time and is private to
* NodeDB.cpp in the device code.
*/
uint32 version = 2;
}
/*
* The on-disk backup of the node's preferences
*/
message BackupPreferences {
/*
* The version of the backup
*/
uint32 version = 1;
/*
* The timestamp of the backup (if node has time)
*/
fixed32 timestamp = 2;
/*
* The node's configuration
*/
LocalConfig config = 3;
/*
* The node's module configuration
*/
LocalModuleConfig module_config = 4;
/*
* The node's channels
*/
ChannelFile channels = 5;
/*
* The node's user (owner) information
*/
User owner = 6;
}