Use RX-only radio recovery and feed the repeater reboot watchdog after MeshCore parsing. Default to 24 hours, apply temporary watchdog and advert intervals in RAM, and report temporary durations as days, hours, and minutes. Add regression coverage and an ESP-NOW bridge setup guide.
Port the observer doc cleanup from observer-firmware (4beb5472) onto dev,
keeping dev-specific content intact.
- move internal mechanics into MQTT_INTERNALS.md: deferred construction,
runtime slot memory, backoff/circuit breaker, message building, command
namespacing, and the legacy prefs key mapping
- drop the duplicated First-Time Setup, Command Architecture, and SNMP
Monitoring sections, folding their unique steps into Quick Start
- condense the partition/NVS prose and merge the five custom-broker
examples into one Custom Brokers section
- promote the preset list to a top-level Broker Presets section with an
Extra setup column, and document the presets the table was missing:
meshcore-fi, corecomms, mesh-chaun14, wcmesh, and meshtexas
- fix the coloradomesh port (443, not 1883)
- point flasher and changelog links at observer.gessaman.com
- restore the nbr: status field, which the code still emits, and correct
the neighbors topic to QoS 0 retained per allow_retain
Dev-specific content is preserved as-is: per-slot packet filters, the Web
Configuration Portal, local testing without hardware, MeshRank's raw
exclusion, and neighbors default_scope.
First upstream merge since the 2026-06-06 base (191 upstream commits). 14 files
conflicted; resolutions below.
Fleet-critical check (Constraint 1): upstream reordered NodePrefs members
(rx_boosted_gain / path_hash_mode moved to the struct tail) but did NOT change
/com_prefs. Persistence is written field-by-field at explicit offsets, so member
order is in-memory only. Verified the fork's writeCommonPrefsImage() is
byte-identical to upstream's inline writer at every offset (79 pad, 121, 122,
290-294). No migration needed.
Resolutions:
- CommonCLI.h: kept the fork's NodePrefs (superset) and adopted upstream's
setRxBoostedGain(bool)->bool signature change, which CommonCLI.cpp now uses to
report unsupported. Corrected a stale comment claiming rx_boosted_gain lives at
offset 79 (it is a pad; the field is at 290).
- CommonCLI.cpp: kept the fork's legacy /com_prefs migration and the extracted
writeCommonPrefsImage() call.
- UITask.cpp: three-way merge - upstream's drawTextCentered + powering-off
screen, plus the fork's WITH_WEBCONFIG portal/reboot screens.
- ESP32Board.cpp, MeshCore.h, platformio.ini: kept both sides (fork OTA additions
alongside upstream powerOff/enterDeepSleep and Packet.cpp).
- MicroNMEALocationProvider.h: took upstream's claim/release and added the
_claims member they depend on.
- MyMesh.cpp/.h (repeater + room server): kept the fork's superset defaults.
- Removed duplicate declarations auto-merge produced: RadioLibWrapper::_cad_enabled
and MyMesh::getCADEnabled().
Verification: native suite 15/15 (incl. upstream's new test_mesh_tables), both
MQTT smoke builds green, ArduinoJson pin check passes. Hardware validation next.
Integrates Mike Carper's transmission-reliability work (direct retries with
SNR-adaptive backoff and CR, flood retry controls, alt-path replies, flood
channel gates) plus its upstream/dev base (as of 2026-07-06) on top of the
observer stack. The flex branch is untouched; this branch is the experimental
integration line.
Conflict-resolution decisions, for future re-syncs (git rerere is enabled and
has recorded these):
- NodePrefs adopts keymind/upstream member order + retry/flood tail. Member
order is in-memory only: /com_prefs stays field-by-field with the same
canonical file order both sides already share through offset 294; keymind
appends the retry tail at 295+ (new canonical size 676). Flex fleet files
load unchanged; retry fields default via direct_retry_prefs_magic.
- loadPrefsInt keeps the fork's legacy MQTT-gap recovery but moves its
detection boundary from 'extra > 5' to 'extra > LEGACY_MQTT_GAP_3SLOT (864)'
so keymind-size tails take the normal read path. COM_PREFS_TAIL_BYTES
retired.
- Dispatcher/RadioLibWrappers: fork watchdog additions + keymind TX overrides
and CAD busy counter are unioned; RxReservePacketManager::queueOutbound
follows upstream's new bool return (false when shedding).
- CommonCLI: fork observer dispatch + versioned /mqtt_prefs machinery kept;
keymind CLI (retry/flood/radioat) taken; duplicate CAD/FEM handlers and
sanitise lines deduped (kept keymind placements to minimize future diff).
- MyMesh (repeater/room): fork alerter/OTA/observer wiring kept; keymind
scheduled-radio system replaces the old pending_* temp-radio members;
applySavedRadioParams() replaces raw setParams at startup.
- ESP32Board: fork manifest-OTA + keymind powerOff/deepSleep and stopOTAUpdate
unioned; startOTAUpdate keeps fork's STA-aware IP with keymind's idempotency
guard.
- build.sh taken wholesale from keymind (fleet builds use GH Actions).
Verified: Heltec_v3_repeater_observer_mqtt, Heltec_v3_repeater,
heltec_v4_repeater_observer_mqtt, Heltec_v3_room_server_observer_mqtt build;
host migration harness (13 MQTT + non-MQTT scenarios) passes with updated
expectations (676-byte /com_prefs; odd-size files normalize on save, not
load); native unit tests 13/13.
This is a key difference compared to other systems and I see people
asking this a lot. It is mentioned in the FAQ but let's make it more
prominent in the README.
Added small section under RAK compatibility for info on how to convert hex to uf2, with link to Microsoft GitHub uf2conv python script. Cleaned up how links display in that section.