Make sleep tracking work, and suppress only auto-reconnect rather than discovery#89
Open
kmatzen wants to merge 1 commit into
Open
Make sleep tracking work, and suppress only auto-reconnect rather than discovery#89kmatzen wants to merge 1 commit into
kmatzen wants to merge 1 commit into
Conversation
…n discovery setDeviceSleeping wrote through an optional chain into discoveredDevices and connectedDevices. Both are only ever populated by addDiscoveredDevice, which nothing in the codebase calls, so both are permanently empty: the setter was a silent no-op and isDeviceSleeping always returned false. Sleep was therefore never suppressing anything, and the app would immediately re-discover and reconnect a camera the user had just put to sleep. Simply recording the flag is not enough, and neither is any refinement of it. Suppressing discovery for a camera believed asleep makes it permanently unreachable: it is withheld from discoveredGoPros both on disconnect and on every advertisement, and connectToGoPro requires it to be there, so the user has no way to reconnect. Adding a timed grace window does not fix this — a camera still advertising when the window closes gets re-discovered mid-shutdown, undoing the sleep command. Gating on observed silence instead fails the other way: a camera woken before the app notices silence stays invisible forever. The ambiguity is fundamental. A camera still shutting down and a camera that just woke up emit identical advertisements, so no rule over advertisements plus elapsed time can separate them. The guard conflated two concerns — do not auto-reconnect a camera the user slept, and do not show it — and only the first was ever required. Discovery is now never suppressed, so the camera stays visible and manually connectable; the sleep flag gates scheduleReconnectIfNeeded and the straggler retries instead. That needs no assumption about how long shutdown takes. Sleep state now lives in its own dictionary rather than hanging off the device records that are never populated, so it cannot silently no-op again. The same applies to power-down tracking, which was inert for the identical reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AqfipPBp3eErDgZboooqxP
kmatzen
force-pushed
the
fix/packet-reassembly
branch
from
July 19, 2026 04:45
372aafd to
2f8cee9
Compare
kmatzen
force-pushed
the
fix/sleep-visibility
branch
from
July 19, 2026 04:48
3422467 to
303e745
Compare
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.
Third of four stacked PRs. Base is
fix/packet-reassembly(#88), notmain.This one changes user-visible behaviour, so the reasoning matters more than the diff.
Sleep tracking never worked at all
setDeviceSleepingwrote through an optional chain intodiscoveredDevicesandconnectedDevices. Both are only ever populated byaddDiscoveredDevice— which nothing calls. Both dictionaries are permanently empty, so the setter was a silent no-op andisDeviceSleepingalways returnedfalse.Net effect today: the app immediately re-discovers and reconnects a camera you just put to sleep.
Why just recording the flag is not the fix
Suppressing discovery for a camera believed asleep makes it permanently unreachable: it is withheld from
discoveredGoProsboth on disconnect and on every advertisement, andconnectToGoProrequires it to be there. The user has no way back.I modelled the alternatives in TLA+ (
specs/SleepState.tla, included in the next PR). Every advertisement-based design fails one of two properties:The timed-window version is the one I wrote first and believed was correct. TLC found the counterexample in seven steps: the camera is still advertising when the window closes, so the app re-discovers it mid-shutdown.
The ambiguity is fundamental — a camera still shutting down and a camera that just woke up emit identical advertisements. No rule over advertisements plus elapsed time can separate them, so every such design must choose which way to be wrong.
The change
The old guard conflated two concerns — do not auto-reconnect a camera the user slept and do not show it — and only the first was required. Discovery is never suppressed now; the flag gates
scheduleReconnectIfNeededand the straggler retries. No assumption about shutdown duration anywhere.One property I deliberately did not assert: never auto-reconnecting during shutdown. TLC shows it conflicts with honouring manual override — if the user taps connect mid-shutdown, that clears the flag, and a later auto-reconnect is then correct.
Testing
135 tests pass, including seven new ones. Mutation-verified: reverting sleep storage to the dictionary-backed version fails the two tests that assert the flag actually persists.
Three of the seven still pass under that mutation, because they assert absence of sleep state — trivially true when the getter always returns false. They guard against regressions in the other direction; they are not evidence the fix works.
Review notes
Not verified against hardware. The behaviour change is worth exercising with a real camera: sleep a camera, confirm the app stops reconnecting it, confirm it stays visible in the list, and confirm tapping it reconnects.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AqfipPBp3eErDgZboooqxP