feat(repeater): politeness knobs in Settings (skip-advert, max-hops, yield, min-SNR)

Four opt-in filters, all default off, consulted only when the repeater is on
(MyMesh::allowPacketForward) and shown under Settings > Radio only while it is:
- Skip advert: don't re-flood ADVERT packets (highest-volume flood traffic).
- Max hops: drop a flood packet once it has travelled N hops.
- Yield: scale the FORWARDED flood retransmit delay so a mobile companion
  defers to better-sited fixed repeaters; never touches the node's own sends.
- Min SNR: drop a flood copy received below a dB threshold so marginal fringe
  traffic isn't re-flooded.

All four are flood-only — on a direct route this node is the named next hop, so
dropping there would kill delivery. Persisted behind a new schema sentinel
(0xC0DE000E) with stray-byte clamps; min-SNR uses a -128 "disabled" sentinel so
an upgraded file can't read as "filter at 0 dB".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-06-18 23:44:36 +02:00
co-authored by Claude Sonnet 4.6
parent f55b869fbe
commit e213ff6efb
4 changed files with 120 additions and 2 deletions
+19 -1
View File
@@ -152,11 +152,29 @@ struct NodePrefs { // persisted to file
static const uint8_t USER_RADIO_PRESET_MAX = 4;
UserRadioPreset user_radio_presets[USER_RADIO_PRESET_MAX];
// Repeater "politeness" — only consulted when client_repeat is on, via
// MyMesh::allowPacketForward(). Both default to off (0) so behaviour is
// unchanged until the user opts in (Settings > Radio).
// repeat_skip_adverts: 1 = don't re-flood ADVERT packets (the highest-volume
// flood traffic); messages/acks still relay.
// repeat_max_hops: drop a flood packet once it has already travelled this
// many hops. 0 = no hop limit.
// repeat_delay_boost: extra retransmit-delay multiplier for FORWARDED floods
// only (own sends are unaffected) — a mobile companion yields to better-sited
// fixed repeaters. Effective delay = base * (1 + repeat_delay_boost). 0 = off.
// repeat_min_snr: drop a flood packet received below this SNR (dB), so marginal
// fringe traffic isn't re-flooded. REPEAT_SNR_DISABLED (-128) = off.
uint8_t repeat_skip_adverts;
uint8_t repeat_max_hops;
uint8_t repeat_delay_boost;
int8_t repeat_min_snr;
static const int8_t REPEAT_SNR_DISABLED = -128;
// Tail sentinel written at the end of /new_prefs. Bump the low byte when
// adding/removing/reordering fields in DataStore::savePrefs/loadPrefsInt so
// older saves are detected on load and skipped (zero-init defaults kept).
// High 24 bits identify the file format; low byte is the schema revision.
static const uint32_t SCHEMA_SENTINEL = 0xC0DE000D;
static const uint32_t SCHEMA_SENTINEL = 0xC0DE000E;
// Bit-index for each home page. Used by page_order (entries store bit+1) and
// by home_pages_mask. Single source of truth — both HomeScreen::pageBit/bitToPage