Fix fixed-position broadcasts going out as lat/lon 0,0 (#11985)

handleReceivedProtobuf() returns early for a fixed-position self-update, to
protect the pinned coordinates from being overwritten by a phone/GPS update -
but that early return also skipped the line that refreshes the `precision`
member for the packet's channel, leaving it at its 0 "safe starting value".

alterReceivedProtobuf() then runs anyway on the same from-us packet (whether
it's our own broadcast looped back locally, or a phone-submitted one) and
truncates it to whatever `precision` currently holds. applyPositionPrecision(_,
0) doesn't clamp - it wipes the whole Position back to defaults, intentionally,
for the channel-privacy case this function was written for. Router::deliverLocal()
runs this same dispatch on the same packet object before it's actually
transmitted, so the wipe landed in the real outgoing radio packet: every
fixed-position broadcast went out as lat=0/lon=0 instead of the fixed
coordinates.

Fix: refresh `precision` on this early-return path too, instead of skipping
it. For our own already-correctly-truncated broadcast this makes
alterReceivedProtobuf()'s re-truncation a no-op (same precision, idempotent).
For a phone-submitted position while fixed_position is on, it's what
correctly applies the channel's privacy truncation - preserving that behavior
was the point of not touching alterReceivedProtobuf() itself. (An earlier
version of this fix skipped alterReceivedProtobuf() entirely whenever
fixed_position was set, which would have let a phone-submitted position
broadcast at full precision regardless of channel setting - caught in review.)

Regression range: v2.7.24 through current develop (introduced in #10383,
which removed the `precision > 0` guard that used to make this a no-op).
v2.7.23 and earlier are unaffected.

Tested on a Portduino/meshtasticd build with position.fixed_position set:
confirmed periodic position broadcasts carried the configured coordinates
instead of 0,0 after this change. Not tested against ESP32/nRF52 hardware -
the affected code path is platform-generic (no ARCH_* gating), so the fix
should apply equally, but I don't have that hardware on hand to verify.

Fixes #11547


Claude-Session: https://claude.ai/code/session_01N7q3Vu58yzcdcP5hCW2au6

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
danandClaude Sonnet 5 authored and GitHub committed 2026-09-27 12:58:55 +00:00
1 parent d6307752c7
commit d482dc78a1
1 file changed
+6
+6
View File
@@ -84,6 +84,12 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
#endif
nodeDB->setLocalPosition(p, true);
// Keep `precision` current for this channel even on this early-return path -
// alterReceivedProtobuf() runs right after handleReceived() on this same packet
// (MeshModule::callModules()) and depends on it to truncate correctly, whether this
// packet is our own already-truncated broadcast (re-truncating is a no-op) or a
// phone-submitted one that still needs it applied.
precision = getPositionPrecisionForChannel(mp.channel);
return false;
} else {
LOG_TRACE("Incoming update from MYSELF");