Commit Graph
1000 Commits
Author SHA1 Message Date
agessaman 1d839e4479 feat(examples): wire remote-command ACL + CLI callbacks
Add a shared MQTTRemoteCallbacks.h (ACL admin authorizer + CLI executor
adapters) and register them on the bridge in the repeater and room-server
examples right after construction, at every bridge-creation site.
2026-07-21 10:00:21 -07:00
agessaman 7b68371a7f feat(alerts): enhance alert test command response for clarity
Improve the response message for the `alert test` command to clarify
that a successful test send does not guarantee automatic alerts are
enabled. This change helps prevent confusion for operators regarding
the status of the alert system after testing.
2026-07-20 19:21:29 -07:00
agessaman 85c0e1de11 feat(mqtt): implement neighbor discovery and management in MyMesh
Add support for neighbor discovery and management in the MyMesh class.
This includes structures for neighbor information, methods for handling
neighbor advertisements, and control data reception. The new features
allow for dynamic neighbor management, enhancing the mesh network's
capabilities. Additionally, the maximum number of neighbors is set to
50 across various platform configurations.
2026-07-20 08:47:37 -07:00
Adam GessamanandGitHub 329d7f86c2 Merge pull request #36 from agessaman/webconfig
Implement MQTT neighbors feature with webconfig integration
2026-07-19 23:28:02 -07:00
agessaman 634d98c2f7 feat(mqtt): implement custom JSON document allocator for neighbors 2026-07-19 23:22:55 -07:00
agessaman 34a8220111 feat(mqtt): add neighbor-scope discovery + periodic publish to MyMesh
Port the neighbor-discovery state machine from mqtt-bridge-implementation-flex,
adapted to this branch's MyMesh (WebConfig members shifted the insertion points;
applied by content).

- Two-stage periodic refresh in loop() driven by mqtt_neighbors_interval:
  stage 1 is a zero-hop sendNodeDiscoverReq() (reuses the existing 60s window),
  stage 2 (startNeighborDiscover) fires one anon-regions scope query per heard
  neighbour, then finishNeighborDiscover() builds the table JSON via
  MQTTMessageBuilder::buildNeighborsMessage and hands it to
  bridge->requestPublishNeighbors().
- Peer overlay at NEIGHBOR_DISCOVER_PEER_BASE lets scope-query RESPONSE packets
  from non-ACL neighbours decrypt: searchPeersByHash prepends heard neighbours
  (bounded by MAX_CLIENTS), getPeerSharedSecret derives the secret on the fly,
  and onPeerDataRecv routes both overlay-index and ACL-client-that-is-a-neighbour
  responses into handleNeighborDiscoverResponse.
- Entries ordered most- to least-useful (recent, then stronger SNR) so the JSON
  builder's tail-drop keeps the useful head.
- `discover.scopes` CLI command (manual trigger), with a WITH_MQTT_BRIDGE stub
  replying "requires PSRAM" on non-PSRAM builds.
- Reports schedule to the bridge each loop via setNeighborsSchedule().
- Uses ArduinoJson v7 JsonDocument (not deprecated DynamicJsonDocument).

All gated on WITH_MQTT_NEIGHBORS. Reuses the existing MQTTBridge* member.
Verified: T_Beam_S3_Supreme_SX1262_repeater_observer_mqtt builds [SUCCESS].
2026-07-19 22:39:41 -07:00
agessaman 76a3300cc4 fix(repeater): restore node name at top of home screen
A merge conflict resolution collapsed the `// node name` comment and its
`_display->setCursor(0, 0)` call onto a single line, which commented out
the cursor reset. The node name then rendered at whatever cursor position
was left over from the previous frame (the end of the IP: line), so it
trailed the IP address and wrapped onto the next line instead of appearing
at the top of the home screen.

Split the comment and setCursor back onto separate lines so the name is
drawn at (0, 0) again.
2026-07-19 18:17:21 -07:00
agessaman 25bfac0e93 fix: remove duplicate declarations left by the upstream merge
The 2026-07-19 upstream merge auto-merged two additions into the same class
bodies without conflicting, producing duplicate declarations:

  examples/simple_room_server/MyMesh.h  - getCADEnabled()
  variants/heltec_v4/HeltecV4Board.h    - setLoRaFemLnaEnabled(),
                                          canControlLoRaFemLna(),
                                          isLoRaFemLnaEnabled()

Same class of breakage as the RadioLibWrapper::_cad_enabled and
MyMesh::getCADEnabled() duplicates already fixed in the merge commit. These
survived because the merge was validated with the two prescribed MQTT smoke
builds, and neither of them compiles simple_room_server or the heltec_v4
variant - so CI was the first thing to touch the broken files.

Now verified across ALL 32 observer envs locally, not a sample: 32/32 build.
2026-07-19 15:49:27 -07:00
agessaman 15e3400a28 merge: upstream/dev into webconfig (v1.16.0 base -> 2026-07-19)
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.
2026-07-19 12:41:29 -07:00
agessaman f68a0fb9e7 feat(ota): broadcast OTA start/fail milestones on the alert channel
An operator who triggers `ota update` via remote management only sees the
command's reply; the actual OTA runs ~2.5s later and reboots on success,
so the start/fail notifications land outside the reply window. Mirror the
key OTA milestones onto the configured alert channel (in addition to the
Serial log):

- START ("OTA update starting") from beginDeferredOtaUpdate(), i.e. while
  the loop still runs -- a flood queued at the deferred fire could never
  transmit before the flash blocks the loop / reboots on success.
- FAIL ("OTA aborted: ...") at both abort points (teardown barrier
  withheld flashing; preflight/download error).

Success has no message: a successful flash reboots into the new image, so
the node returning on the new version is the signal.

New MyMesh::otaAlert() gates on the `alert on/off` master switch and rides
the configured alert scope (AlertReporter::sendText -> sendChannel ->
resolveAlertScope); no-op when alerts are off or no channel is set. Only
these start/fail milestones -- routine slot connect/disconnect is
unaffected (stays in AlertReporter's fault logic). Documented in ALERTS.md.
Both observer firmwares build.
2026-07-19 07:51:52 -07:00
agessaman 2e1a1410ce feat(mqtt): cooperative MQTT shutdown + OTA teardown barrier (Phase 5)
Wire the Phase 4 MQTTLifecycle state machine into MQTTBridge to replace the
blind vTaskDelete teardown that could kill the MQTT task mid-mbedTLS and then
free client buffers on a corrupted heap (the observed OTA teardown panic).

- MQTTBridge owns a MQTTLifecycle::Coordinator driven only by the loop task
  (Core 1) from begin()/end(); a nested LifecycleOps binds the host-tested Ops
  spec to FreeRTOS/PsychicMqttClient.
- end() requests a cooperative stop; the MQTT task (Core 0) tears down its own
  clients where the mbedTLS contexts live, acks via _stop_acked, and
  self-terminates. end() waits (bounded) for the ack, then frees queue/buffers.
- Bounded stop timeout -> reviewed fallback (force kill + Core-1 teardown) sets
  a dirty latch that withholds OTA flashing.
- begin() gains an idempotent double-call guard and syncs the Coordinator to
  Running.
- OTA teardown barrier: simple_repeater's deferred flash aborts/resumes unless
  end() reported a clean stop (canFlashAfterStop()).

Scope: minimal cooperative-shutdown unit. The volatile NTP/reconfigure handshake
replacement and the plain-data snapshot / consumer repointing (MQTT_OWNERSHIP.md
sections 1-3) are deferred. MQTT_STOP_TIMEOUT_MS is a Phase-0 placeholder pending
on-hardware characterization.

Native suite green (incl. test_mqtt_lifecycle); both observer firmware smoke
builds compile. Not yet hardware-validated (Phase 7 gate).
2026-07-19 00:25:37 -07:00
agessaman cbbd01b620 feat(docs): add local testing instructions for MQTT functionality
Include detailed instructions for local testing of observer and WiFi
functionality without hardware. Document the use of a mock backend and
Wokwi ESP32-S3 simulation for easier development and testing.
Enhance the MQTT implementation documentation to improve developer
experience and facilitate testing workflows.
2026-07-18 13:19:27 -07:00
agessaman a7c1cc631f feat(webconfig): add web configuration portal and MQTT enhancements
Introduce a web configuration portal for easier node management and
provisioning without serial CLI. Enhance MQTT functionality with
improved IATA code validation, dynamic slot management, and
background NTP synchronization. Update web UI elements for better
user experience and security notes regarding open AP usage.
2026-07-18 09:34:11 -07:00
ripplebizandGitHub 795989b918 Merge pull request #2966 from Quency-D/heltec-rc32
Add Heltec rc32 board
2026-07-17 23:23:29 +10:00
Florent c644720ea7 uitask: screen and radio poweroff moved to board 2026-07-17 08:29:31 -04:00
fdlamotteandGitHub 76c6e73fb6 Merge branch 'dev' into repeater_btn 2026-07-17 06:55:19 -04:00
Quency-D b26f53a263 Avoid waking display from rotary input 2026-07-17 15:35:07 +08:00
agessaman dfee21a0c9 feat(webconfig): implement web configuration portal for ESP32 2026-07-16 17:00:22 -07:00
Quency-D 05d4bd2f7f Add a rotary encoder 2026-07-15 17:45:24 +08:00
ripplebizandGitHub b55d69e57a Merge pull request #1983 from rgregg/rak-ethernet
Support for RAK ethernet module
2026-07-15 18:53:38 +10:00
Jaroslav Škarvada 15e259c572 Added MCU temp sensor to the companion
Fixes #2896
2026-07-14 17:43:33 +02:00
Quency-D 4d0ba1516c Remove the watchdog feeding operation from each iteration of the loop to reduce power consumption. 2026-07-14 17:23:13 +08:00
Ryan Gregg 16b76bd35a Merge remote-tracking branch 'upstream/dev' into rak-ethernet
# Conflicts:
#	examples/companion_radio/main.cpp
2026-07-13 23:06:00 -07:00
Alex Beal 07b543176b Merge branch 'dev' into pr-1446 2026-07-12 15:44:28 -06:00
agessaman 1d52161332 Merge branch 'restore/upstream-duty-cycle' into restore/fem-rxgain 2026-07-09 17:54:45 -07:00
agessaman 1c9c6292e5 fix(mqtt): shed retransmissions, not capture, when duty cycle starves the pool
Load-testing the restored token bucket at 'set dutycycle 1' showed MQTT
capture dropping to exactly the TX rate. Queued retransmissions hold static-
pool packets with no expiry, so throttling parks the whole pool in the send
queue; Dispatcher::checkRecv() then discards received packets before logRx()
ever feeds the bridge — each completed TX frees exactly one packet for
exactly one more RX.

Observer builds now use RxReservePacketManager (fork-owned header): once the
free pool drops below a quarter of the pool, outbound packets are refused and
freed, so RX allocation and MQTT capture continue at full rate while the node
sheds repeat load it has no TX budget for anyway. Non-observer builds keep
upstream pool behavior via the same factory; StaticPoolPacketManager stays
byte-identical to upstream.
2026-07-09 17:54:38 -07:00
agessaman b2e79d4735 fix(radio): drop companion FEM wiring; wire t096 + tracker_v2 FEM overrides
companion_radio has its own NodePrefs without radio_fem_rxgain (matching
upstream, which doesn't wire companion either), so the startup call added in
e905451d broke every companion build:
  MyMesh.cpp:973: error: 'struct NodePrefs' has no member named 'radio_fem_rxgain'
It went unnoticed behind the pre-existing companion build failures.

Also port upstream's FEM LNA overrides for heltec_t096 and heltec_tracker_v2
verbatim (board overrides + isLNAEnabled/const getters), so all three boards
upstream wires now match instead of reporting unsupported. Both variant files
compile; those targets still fail overall on the pre-existing non-observer
MQTT-source build-config issue (unchanged with this work stashed).
2026-07-09 12:25:23 -07:00
agessaman e905451dce feat(radio): drive LoRa FEM RX gain from radio_fem_rxgain (heltec_v4)
Completes the FEM RX-gain restoration begun in the CAD/prefs change, which
persisted radio_fem_rxgain but didn't yet drive the hardware. Also dropped
by the 22eb9b87 revert; restored to match upstream.

- MainBoard: setLoRaFemLnaEnabled()/canControlLoRaFemLna()/isLoRaFemLnaEnabled()
  virtuals (default: can't control — non-FEM boards report unsupported)
- heltec_v4: board overrides driving loRaFEMControl; LoRaFEMControl gains the
  isLNAEnabled() getter (it already tracked lna_enabled and drove the FEM)
- CLI: `set radio.fem.rxgain on/off` / `get radio.fem.rxgain` (guarded by
  canControlLoRaFemLna, so it reports "unsupported" on non-FEM boards)
- app startup applies the persisted pref: board.setLoRaFemLnaEnabled(
  _prefs.radio_fem_rxgain), beside setRxBoostedGainMode

Default is ON (upstream), so on FEM boards the LNA is enabled after upgrade —
a real reception behavior change to confirm on hardware. The other FEM
variants (heltec_t096/tower_v2/tracker_v2) need the same small board-override
addition; until then `radio.fem.rxgain` reports unsupported there (no
regression — status quo).

Builds: heltec_v4 repeater-observer + room-observer (FEM board), Heltec_v3
repeater (non-FEM, base virtuals no-op). NEEDS on-device validation on a
Heltec V4.
2026-07-09 11:20:07 -07:00
agessaman df90673d18 feat(radio): restore CAD support + radio_fem_rxgain persistence (upstream parity)
Continues restoring features dropped by the 22eb9b87 revert. Both were
upstream-tested code, not intentional fork removals.

CAD (hardware Channel Activity Detection / listen-before-talk before TX),
fully restored and functional:
- NodePrefs.cad_enabled + `set cad on/off` / `get cad` CLI (default off)
- RadioLibWrapper: _cad_enabled + setCADEnabled() + the scanChannel()/CAD
  branch in isChannelActive() (Phase 1 already restored the Dispatcher hook)
- getCADEnabled() overrides in the repeater/room/sensor apps (return the
  pref) and companion (always on, matching upstream)

radio_fem_rxgain: the NodePrefs field + /com_prefs persistence are restored
here at upstream's exact offsets (293 fem, 294 cad), which makes /com_prefs
byte-identical to upstream through the tail. The field is persisted and
defaults on (upstream default), but the per-board LNA *driving* + the
`radio.fem.rxgain` CLI are deferred to the FEM-hardware change (they depend
on board methods and want per-board bench testing).

The new-format /com_prefs tail grows from 3 to 5 bytes; the old-format
detection threshold and the host migration harness are updated accordingly
(all scenarios pass, incl. the non-MQTT-build variant).

Builds: Heltec_v3 repeater, repeater-observer, room-observer. (sensor /
plain-room / companion fail only on the pre-existing Timezone.h include
issue, unrelated to these changes.)
2026-07-09 11:12:57 -07:00
Florent 3ee2f77877 restore display and radio poweroff in ui 2026-07-06 08:46:57 -04:00
Florent 2efb3af69b repeater: poweroff on long press 2026-07-06 08:40:56 -04:00
Kevin Le 7d7de88707 board->powerOff() is sufficient to power off radio, display, GPS and components 2026-07-05 21:22:13 +07:00
Quency-DandGitHub 2867542cfa Merge branch 'dev' into solar-watchdog 2026-07-04 16:47:37 +08:00
Neil Alexander 0d7379520f Fix recv_pkt_region incorrect usage
The `recv_pkt_region` is set when processing a flood packet in `filterRecvFloodPacket`
but direct/non-flood packets would never pass through that function, so the pointer was
not cleared for them.

`sendFloodReply` would then later use it blindly, which meant that the response would
either inherit the region from the last flood packet, or refer to a non-initialised pointer
if no region floods had been received yet.
2026-07-02 09:28:41 +01:00
Liam CottleandGitHub dc200cf22d Merge pull request #2639 from sefinek/fix/typos-in-comments
fix: fix typos in source code comments
2026-06-27 11:26:54 +12:00
agessaman 2eb41baeda refactor(mqtt): migrate observer settings to MQTTPrefs structure
Refactored the handling of observer-related settings by moving them from
NodePrefs to a new MQTTPrefs structure. This change centralizes MQTT,
WiFi, timezone, SNMP, and alert configurations, improving code organization
and maintainability. The new structure allows for better separation of
concerns and prepares the codebase for future enhancements.
2026-06-26 08:59:48 -07:00
taco 1f9bb67400 return bool when setting rx boost 2026-06-26 07:44:01 +10:00
taco 5d0ff7fe6e remove guard on MyMesh::setRxBoostedGain() 2026-06-26 07:06:37 +10:00
agessaman 7416d632b9 feat(mqtt): add NTP server configuration and diagnostics commands
Implemented new commands for configuring and diagnosing NTP server
settings in the MQTT bridge. Users can now set a custom NTP server
and probe connectivity to configured servers. This enhancement
improves time synchronization reliability for JWT authentication
and provides better diagnostics for NTP connectivity issues.
2026-06-24 17:14:11 -07:00
agessaman 125ddac184 feat(ota): add partition-table signature handling for OTA updates
Implemented functionality to generate and compare partition-table
signatures during OTA updates. This enhancement ensures that the
target build's partition layout matches the device's actual layout,
improving the reliability of OTA updates and preventing issues
related to partition changes.
2026-06-23 15:38:10 -07:00
agessaman 730eb37dbd feat(ota): implement build number suffix for firmware versioning
Enhanced the firmware versioning system by appending a build number
suffix when available, allowing for better tracking of published builds.
This change improves the OTA update process by providing clearer
versioning information in the embedded firmware string.
2026-06-23 12:55:07 -07:00
agessaman c1885fcc15 feat(ota): implement deferred OTA update scheduling and handling
Added support for deferred OTA updates in the MyMesh class, allowing
the system to schedule firmware updates to occur after a confirmation
reply is sent. This change improves the user experience by ensuring
that the update process does not block the main application loop,
allowing for smoother operation during firmware updates.
2026-06-22 22:33:57 -07:00
Ryan Gregg a206f3e066 Merge remote-tracking branch 'upstream/dev' into rak-ethernet
# Conflicts:
#	docs/faq.md
#	examples/companion_radio/main.cpp
2026-06-20 14:39:03 -07:00
agessaman 985fda1382 Add AlertReporter integration to MyMesh 2026-06-17 20:02:39 -07:00
Wessel Nieboer 7c8e092457 Have CAD be a separate toggle (set cad on/off) 2026-06-14 15:20:58 +02:00
Wessel Nieboer 4f9a091671 Use hardware channel activity detection for checking interference 2026-06-14 15:19:18 +02:00
Scott Powell 2e73fe948e * fix for anon lastmod 2026-06-14 18:54:51 +10:00
Scott Powell 07648e3344 * fix for anon contacts when full 2026-06-14 17:50:41 +10:00
Quency-D 5300fa18c7 Restore companion NodePrefs file ending 2026-06-13 17:40:11 +08:00
Quency-D 3ee58fd2e3 Remove companion FEM RX gain command IDs 2026-06-13 17:31:54 +08:00