fix(ws): remove periodic status broadcast; align push pattern with BT#62
Open
skialpine wants to merge 2 commits into
Open
fix(ws): remove periodic status broadcast; align push pattern with BT#62skialpine wants to merge 2 commits into
skialpine wants to merge 2 commits into
Conversation
The /snapshot WebSocket was the only protocol pushing periodic state
snapshots. BT notifies only weight + on-event (power_off, buttons); USB
binary follows the same shape. WiFi did a periodic status frame every
5 s when events_enabled, which:
- allocated ~310 B x N clients every 5 s for state the on-device web
apps never consumed (verified: zero references to battery_percent,
timer_seconds, charging, low_power, etc. in web_apps/)
- was the dominant heap-pressure source in the 8 h soak that
motivated PR decentespresso#61
- was inconsistent with BT, surprising clients that interoperate
across both transports
After this change, clients request status on demand via
{"command":"status"} -- same model as BT's 0x22 voltage request, same
per-client reply path that already exists (sendWebsocketStatus, kept
intact). The events_enabled flag now gates only button events and
power_off broadcasts -- the cross-protocol event types that BT also
notifies, just without an opt-in over there. Weight, button, and
power_off push behavior on WiFi is unchanged.
Cleanup follows:
- sendWebsocketStatusAll() removed (no callers; was the periodic
broadcast helper)
- t_lastWebsocketStatusUpdate global removed (no periodic tick to
track)
- WEBSOCKET_STATUS_NOTIFY_INTERVAL_MS constant removed
- WS event handler no longer initialises/resets the period timer
- README updated: status frame is on-request only; the "events on"
paragraph no longer mentions periodic status; cross-references the
BT pattern explicitly
Verified on hardware:
20 s window, events on, rate 10k -> 201 weight frames (10.05 Hz)
+ 0 status frames. On-request {"command":"status"} still answers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three findings from the code review on cb569d3: 1. include/websocket.h:166 heap-gate doc-comment claimed "Skipping a frame is invisible (the next weight frame is <=500 ms away, status <=5 s); crashing is not." The "status <=5 s" recovery guarantee no longer holds after this PR removes the only periodic status broadcaster. Rewrote to describe what's actually still gated by wsBroadcastHeapOk (weight + button + power_off). 2. include/websocket.h:243-247 had an addendum paragraph framing the surviving printfAll comment as "Note: status is no longer broadcast periodically...". The historical framing reads as documentation for a function that no longer exists; dropping it leaves the printfAll technical commentary applying cleanly to sendWebsocketWeightAll (which is what it now sits above). 3. sendWebsocketStatus (include/websocket.h:224-225) reads stopWatch directly from the AsyncTCP task. CLAUDE.md threading model #1 footgun: "stopWatch.* -- No -- multi-field (running flag + start ts + accumulator) and also mutated from loop(), BLE and USB; a status- frame read can tear a write across tasks." The bug is pre-existing on main (not introduced by this PR), but CLAUDE.md's "Fixing bugs you find along the way" applies. Mirroring the snapshot pattern used by PR decentespresso#57: new g_timerRunning/g_timerElapsed volatiles in parameter.h, refreshed once per main-loop pass in src/hds.ino's WiFi-housekeeping block, read by sendWebsocketStatus. (PR decentespresso#57 adds the same snapshot independently; merge order between decentespresso#57 and decentespresso#62 will produce a trivial same-lines conflict that git auto-resolves.) Verified on hardware: flash + 12s window with events on + rate 10k -> 121 weight frames at 10 Hz, 0 periodic status frames; on-request {"command":"status"} returns the full 16-field frame with timer_running/timer_seconds populated from the snapshot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
Code reviewFound 3 issues in cb569d3, all addressed in 7c3b004:
Note: PR #57 adds the same 1 below-threshold issue (50-74)
Verified on hardware after the fix commit: 12 s window with 🤖 Generated with Claude Code If this code review was useful, please react with 👍. Otherwise, react with 👎. |
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.
Summary
The
/snapshotWebSocket was the only protocol pushing periodic state snapshots. BT notifies only weight + on-event; USB binary follows the same shape. WiFi did a periodictype:\"status\"frame every 5 s whenevents_enabled— for state that nothing on-device consumed and that was the dominant heap-pressure source in PR #61's 8 h soak.After this PR, clients get state on demand via
{\"command\":\"status\"}— same model as BT's0x22voltage request, same per-client reply path that already exists. No protocol field is removed; the status frame shape is unchanged, it's just no longer pushed automatically.Why
web_apps/{Quality_Control_Assistant,Weigh_Save,dosing_assistant,index.html}) have zero references tobattery_percent,timer_seconds,charging,low_power, etc. Grepped. Verified.What's preserved
sendWebsocketStatus(client, ...)— per-client reply to{\"command\":\"status\"}/battery/info. Unchanged.sendWebsocketButton,sendWebsocketPowerOff— event-driven broadcasts. Still gated onb_websocketEventsEnabled. Unchanged.protocol_version,firmware_version, battery, timer state, etc.). Unchanged.What's removed
sendWebsocketStatusAll()function (no callers after this PR)loop()that called it every 5 st_lastWebsocketStatusUpdateglobal (no period timer to track)WEBSOCKET_STATUS_NOTIFY_INTERVAL_MSconstantBackward compat
The
events oncommand still works and still controls button + power-off event broadcasts. Clients that were relying on the 5 s periodic status push need to poll{\"command\":\"status\"}themselves (any cadence they want). Existing clients that ignore status frames they didn't ask for are unaffected.Test plan
pio run -e esp32s3) — RAM 16.8%, Flash 45.5%events on+rate 10k→ 201 weight frames at 10 Hz, 0 status frames (would have caught 4 periodic status frames if leaking){\"command\":\"status\"}still answers with the full 16-field frame🤖 Generated with Claude Code