MeshCore bearer: neighbour routing + adaptive airtime/channel monitoring + review fixes (#155, #157) - #162
Merged
Merged
Conversation
…155, #157) #155 - route a configured neighbour over MeshCore: additive DbNeighbour.MeshCoreChannel copied through RouteBuilder, so a neighbour with a channel hint is selected by the bearer. #157 - adaptive airtime + channel monitoring: ChannelMonitor estimates channel occupancy from LOG_RX_DATA (0x88) overheard-packet events; the bearer does listen-before-talk and refuses sends when the channel is congested (a dynamic good-citizen control on top of the static budget), with per-node threshold jitter for fairness. Configurable via DAPPS_MESHCORE_CONGESTION_BACKOFF_FRACTION / _LBT_GUARD_MS. Validated on air (backoff triggered at ~21% occupancy). Fixes from an adversarial review of the bearer: - CRITICAL: SystemOptionsStore.Parse/SaveAsync never read/wrote the MeshCore* keys, so the bearer could not be enabled or configured via the persisted table. Both directions fixed; round-trip regression test added. - MeshCoreInbound: cancel the losing wait so idle iterations don't leak semaphore waiters. - MeshCoreLink: dispose the client if configuration fails after Open (SerialPort/read-loop leak); swallow a dispose-race on send. - MeshCoreFrames: length-guard every parser; DrainAsync skips a malformed frame instead of dropping the whole batch. - TxBudget.Refund: return airtime reserved for a send that didn't go on air. - OutboundMessageManager: audit-label MeshCore forwards as "meshcore". Tests: 17 MeshCore unit tests; full solution builds clean. On-air soak (two Heltec V3s) healthy incl. watchdog reset+recovery and adaptive backoff. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KLbwvhE2cKCe8WPZNg8k17
This was referenced Jul 1, 2026
M0LTE
added a commit
that referenced
this pull request
Jul 1, 2026
Make the MeshCore bearer operable from the dashboard, not just DAPPS_MESHCORE_* env vars: - Settings page: a "MeshCore bearer" panel with every MeshCore option (enable, port, region preset, TX power, channel/PSK, node name, airtime budget, compression, congestion/LBT, reliability), rendered from and saved back through /Config. - A live status line (link state, freq/SF/CR, occupancy, delivered, reliability confirmed/pending, resets) polling /MeshCore/status, plus a "Reset radio" button that drives the watchdog recovery via /MeshCore/reset. - MeshCoreController: GET /MeshCore/status, POST /MeshCore/reset. MeshCoreBearer exposes GetStatus() + ResetRadioAsync(). Also closes a latent trap: /Config model-binds and SaveAsync upserts the WHOLE SystemOptions, so once SaveAsync learned the MeshCore keys (#162), a save from the form (which didn't render them) would have written MeshCore defaults and clobbered the config. Rendering them in the form fixes that. uitest: the Settings panel-groups spot-check now includes MeshCoreEnabled/Region. Claude-Session: https://claude.ai/code/session_01KLbwvhE2cKCe8WPZNg8k17 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-ups to the MeshCore bearer (#154), plus fixes from an adversarial code review.
#155 — route a configured neighbour over MeshCore
Additive
DbNeighbour.MeshCoreChannelcopied throughRouteBuilder, so a neighbour with a channel hint is selected by the bearer (positive selection). Makes outbound usable from operator config.#157 — adaptive airtime + channel monitoring
ChannelMonitorestimates channel occupancy from the radio'sLOG_RX_DATA(0x88) overheard-packet events; the bearer does listen-before-talk and refuses sends when the channel is congested — a dynamic good-citizen control on top of the static airtime budget. Per-node threshold jitter for fairness. Configurable viaDAPPS_MESHCORE_CONGESTION_BACKOFF_FRACTION/_LBT_GUARD_MS. Validated on air: backoff triggered when a node measured the channel ~21% busy.Review fixes (adversarial multi-agent review)
SystemOptionsStore.Parse/SaveAsyncnever read/wrote theMeshCore*keys → the bearer could not be enabled or configured via the persisted table. Fixed both directions + round-trip regression test.TxBudget.Refundreturns airtime reserved for a send that didn't go on air.meshcore.Validation
Builds on #161. Inert unless
MeshCoreEnabled=true;DbNeighbour/BackhaulRoutechanges are additive.🤖 Generated with Claude Code
https://claude.ai/code/session_01KLbwvhE2cKCe8WPZNg8k17