Skip to content

fix(firmware): recover the ESP-NOW send path instead of wedging on it - #1820

Open
clonea1 wants to merge 1 commit into
ruvnet:mainfrom
clonea1:contrib/espnow-recovery
Open

fix(firmware): recover the ESP-NOW send path instead of wedging on it#1820
clonea1 wants to merge 1 commit into
ruvnet:mainfrom
clonea1:contrib/espnow-recovery

Conversation

@clonea1

@clonea1 clonea1 commented Sep 4, 2026

Copy link
Copy Markdown

esp_now_send() failures were counted and otherwise ignored, and a send whose
completion callback never fires leaves the in-flight counter permanently above
its limit. Once that happens the node stops beaconing for the rest of its boot:
every subsequent send is refused by its own back-pressure check, nothing ever
decrements the counter, and there is no path back. The node looks alive, keeps
capturing CSI, and silently stops participating in mesh time sync.

Three guards, all bounded:

ESPNOW_STALL_US a send in flight with no callback for a second is
treated as lost rather than waited on forever
ESPNOW_MAX_INFLIGHT back-pressure, so a stalled peer cannot queue
without limit
ESPNOW_FAIL_BEFORE_RECOVERY consecutive hard failures trigger a deinit/init
cycle rather than an unbounded retry loop

espnow_recover() takes a reason string and logs it, because a node that
recovers silently is indistinguishable from one that never had a problem, and
the distinction matters when deciding whether a site has an RF issue.

Deliberately excluded: deriving the beacon period from the provisioned fleet
size is a separate concern that happened to land in the same commit locally.
This branch keeps the fixed BEACON_PERIOD_MS.


Rebased onto current main before opening: staged before today's seven merges, so it needed replaying to avoid reading as a revert of them. Clean rebase, no files deleted.

esp_now_send() failures were counted and otherwise ignored, and a send whose
completion callback never fires leaves the in-flight counter permanently above
its limit. Once that happens the node stops beaconing for the rest of its boot:
every subsequent send is refused by its own back-pressure check, nothing ever
decrements the counter, and there is no path back. The node looks alive, keeps
capturing CSI, and silently stops participating in mesh time sync.

Three guards, all bounded:

  ESPNOW_STALL_US            a send in flight with no callback for a second is
                             treated as lost rather than waited on forever
  ESPNOW_MAX_INFLIGHT        back-pressure, so a stalled peer cannot queue
                             without limit
  ESPNOW_FAIL_BEFORE_RECOVERY  consecutive hard failures trigger a deinit/init
                             cycle rather than an unbounded retry loop

espnow_recover() takes a reason string and logs it, because a node that
recovers silently is indistinguishable from one that never had a problem, and
the distinction matters when deciding whether a site has an RF issue.

Deliberately excluded: deriving the beacon period from the provisioned fleet
size is a separate concern that happened to land in the same commit locally.
This branch keeps the fixed BEACON_PERIOD_MS.

Co-Authored-By: claude-flow <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant