mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-19 00:56:16 +00:00
ConnectDeviceWebSocket was a one-shot: connect, wait for disconnect, log, return. Once the device-side WebSocket died (idle timeout, blip, speaker reboot), the goroutine ended and conn.WebSocket stayed pointing at the (now-dead) client — which made the duplicate-spawn guard `if device.WebSocket == nil` at the five callsites in handler.go correctly skip spawning, but with nothing else trying to reconnect, the speaker's status flow froze for the rest of the process's lifetime. The browser kept receiving status_update messages on the 5 s ticker (HandleWebSocket), but every payload carried the same stale data the service last knew. Symptom: load the page, NowPlaying shows fresh state; some minutes later, the speaker switches presets or tracks but NowPlaying never updates — even though playback itself works because those are one-shot HTTP calls that don't depend on the WebSocket. Fix: wrap the connect-and-wait in a for-loop with exponential backoff (1 s → 30 s cap, reset on every successful connect). The goroutine now lives for the device entry's lifetime; conn.WebSocket is updated on each successful reconnect and never cleared, so the existing guards keep working without spawning duplicate loops. Pre-existing main bug — preserved by the relocation, surfaced when testing the rebased branch. Fix is contained to the one function; behaviour is byte-identical for the happy path (one connect, no disconnect ever). go build ./... clean. go test ./... clean (only pre-existing TestDocsConsistency fails). golangci-lint run ./... 0 issues. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>