Skip to content

fix(ws_bridge): charge the TX budget by time actually blocked, not wall clock - #310

Merged
eigger merged 1 commit into
masterfrom
fix/ws-bridge-tx-budget-ota-progress
Aug 14, 2026
Merged

fix(ws_bridge): charge the TX budget by time actually blocked, not wall clock#310
eigger merged 1 commit into
masterfrom
fix/ws-bridge-tx-budget-ota-progress

Conversation

@eigger

@eigger eigger commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • TX_LOOP_BUDGET_MS was measured from millis() at loop() entry, but entity state pushes can fire while WsBridgeComponent::loop() never runs at all: http_request's OTA install() defers flash() onto the scheduler, which blocks the entire Application::loop() call for the whole download while publishing update progress about once a second from inside that blocking call.
  • The wall-clock budget read "exhausted" for that entire window, so every progress push landed in tx_queue_ with nothing left to drain it (the component that drains the queue is the very thing not running) — Home Assistant's update progress bar stopped moving after PR fix(ws_bridge): avoid WDT panics, RX poison, and incomplete HA sync #309.
  • Fix: charge the budget by milliseconds actually spent blocking inside send_text_() (a new thin wrapper both send sites now go through), and reset the accumulator after a real idle gap (TX_BUDGET_IDLE_RESET_MS = 500) since the last send. Congested-link protection is unchanged — a freshly reset budget still only allows about the same one or two blocking sends before the next call defers to the queue, so the worst-case single loop() blocking bound (~2s, well under the 5s task WDT) established in fix(ws_bridge): avoid WDT panics, RX poison, and incomplete HA sync #309 is unaffected.

Test plan

  • python -m esphome compile tests/components/ws_bridge/test.esp32-idf.yaml — succeeds (includes the update: platform: ws_bridge / platform: http_request entities exercising this code path).
  • Manual: trigger an OTA install on a real device via HA and confirm the update entity's progress percentage updates continuously instead of freezing after the first push.

🤖 Generated with Claude Code

…ll clock

TX_LOOP_BUDGET_MS was measured from loop() start, but state-push callbacks
can fire while loop() itself never runs — http_request's OTA install()
defers flash() onto the scheduler, which blocks the whole Application::loop()
call for the duration of the download while publishing update progress about
once a second. The wall-clock budget read "exhausted" for that entire window,
so every progress push landed in tx_queue_ with nothing left to drain it,
and Home Assistant's update progress bar stopped moving.

Track milliseconds actually spent inside send_text_() instead, and reset the
accumulator after a real idle gap since the last send. Congested-link
behavior (the ~2s worst-case single loop() bound) is unchanged since a fresh
budget still only allows the same one or two blocking sends before the next
call defers to the queue.
@eigger
eigger merged commit ee8a7e7 into master Aug 14, 2026
3 checks passed
@eigger
eigger deleted the fix/ws-bridge-tx-budget-ota-progress branch August 14, 2026 05:55
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