Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion meshtastic/deviceonly.proto
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,11 @@ message NodeInfoLite {

/*
* Q4-encoded SNR: dB × 4, sint32 zigzag. Matches RouteDiscovery convention.
* Encode: snr_q4 = (int32_t)(snr * 4.0f). Decode: snr = snr_q4 / 4.0f.
* Encode: snr_q4 = (int32_t)lroundf(snr * 4.0f). Decode: snr = snr_q4 / 4.0f.
* float snr is always zeroed on disk; this field carries all persisted SNR.
* A stored 0 does not by itself mean "unknown" here - see NODEINFO_BITFIELD_HAS_SNR in
* src/mesh/NodeDB.h for the presence bit that disambiguates a genuine 0 dB reading from
* "never measured".
*/
sint32 snr_q4 = 19;
Comment on lines +190 to 196

@coderabbitai coderabbitai Bot Jul 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Add the required persistent RSSI field to NodeInfoLite.

The supplied message ends at snr_q4 = 19; it has no rssi = 20 field. Making MeshPacket.rx_rssi optional preserves presence in packets, but cannot persist RSSI across reboots or history replay as required by this PR. Add the documented sint32 rssi = 20 field and ensure its zero-value interpretation uses NODEINFO_BITFIELD_HAS_RSSI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@meshtastic/deviceonly.proto` around lines 190 - 196, Add the persistent RSSI
field to the NodeInfoLite message after snr_q4, using the documented sint32 rssi
= 20 declaration. Ensure persistence and history replay use this field, and
interpret a zero RSSI value through NODEINFO_BITFIELD_HAS_RSSI rather than
treating zero as inherently unknown.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

semantic disagreement, maybe. Can you explain why I need to add a new protobuf?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- NodeInfoLite RSSI / SNR field declarations ---'
rg -n -C 3 '\brssi\b|\bsnr_q4\b' meshtastic/deviceonly.proto

printf '%s\n' '--- RSSI presence bit references ---'
rg -n -C 4 'NODEINFO_BITFIELD_HAS_RSSI|NODEINFO_BITFIELD_HAS_SNR' .

printf '%s\n' '--- NodeInfoLite RSSI assignment/read references ---'
rg -n -C 4 '(NodeInfoLite|node_info|nodeinfo).*rssi|\.rssi\b|->rssi\b' \
  -g '!meshtastic/deviceonly.proto' .

Length of output: 2434


@NomDeTom, fair disagreement — and I should have said a new field in the existing NodeInfoLite protobuf, not “a new protobuf.”

There are two separate persistence cases:

  1. Packet history / receive queue
    DeviceState.receive_queue stores MeshPackets. Making MeshPacket.rx_rssi optional is sufficient to preserve whether that packet had an RSSI reading, including a valid 0 value, when the packet is serialized and replayed.

  2. Latest per-node state after reboot
    NodeDatabase.nodes stores NodeInfoLite, not the packet history. If firmware expects the current/latest RSSI for each node to remain available after a reboot even when the original packet is no longer consulted, then NodeInfoLite needs a persisted RSSI value plus a presence indicator. That is analogous to the existing snr/snr_q4 arrangement.

So: you do not need NodeInfoLite.rssi merely for replaying MeshPacket history. It is needed only if the PR’s intended contract includes persisting the per-node “last RSSI” independently of those packets.

The current protobuf repository has no NODEINFO_BITFIELD_HAS_RSSI definition or firmware read/write path to validate that latter contract; those belong to the related firmware work. My original finding incorrectly bundled packet replay and node-state persistence together.

}
Expand Down
9 changes: 8 additions & 1 deletion meshtastic/mesh.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1848,8 +1848,11 @@

/*
* rssi of received packet. Only sent to phone for dispay purposes.
* Explicit presence: rssi 0 is a legitimate reading on some radios (SX126x can report exactly
* 0 dBm; SX127x's formula can even go positive). has_rx_rssi disambiguates; a replayed packet
* built from history should leave this field absent rather than emitting 0.
*/
int32 rx_rssi = 12;
optional int32 rx_rssi = 12;

Check failure on line 1855 in meshtastic/mesh.proto

View workflow job for this annotation

GitHub Actions / build

Field "12" with name "rx_rssi" on message "MeshPacket" changed cardinality from "optional with implicit presence" to "optional with explicit presence".

/*
* Describe if this message is delayed
Expand All @@ -1864,6 +1867,10 @@
/*
* Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header.
* When receiving a packet, the difference between hop_start and hop_limit gives how many hops it traveled.
* hop_start == 0 does not necessarily mean a direct (0-hop) neighbor: firmware prior to 2.3.0
* never populated this field, so a receiver can only trust hop_start == 0 as genuine once it has
* decoded the packet and confirmed the sender's bitfield is present (added in 2.5.0). Until then,
* or for a sender that never sets that bitfield, treat hop_start == 0 as unknown, not direct.
*/
uint32 hop_start = 15;

Expand Down
Loading