Skip to content

Make sleep tracking work, and suppress only auto-reconnect rather than discovery#89

Open
kmatzen wants to merge 1 commit into
fix/packet-reassemblyfrom
fix/sleep-visibility
Open

Make sleep tracking work, and suppress only auto-reconnect rather than discovery#89
kmatzen wants to merge 1 commit into
fix/packet-reassemblyfrom
fix/sleep-visibility

Conversation

@kmatzen

@kmatzen kmatzen commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Third of four stacked PRs. Base is fix/packet-reassembly (#88), not main.

This one changes user-visible behaviour, so the reasoning matters more than the diff.

Sleep tracking never worked at all

setDeviceSleeping wrote through an optional chain into discoveredDevices and connectedDevices. Both are only ever populated by addDiscoveredDevice — which nothing calls. Both dictionaries are permanently empty, so the setter was a silent no-op and isDeviceSleeping always returned false.

Net effect today: the app immediately re-discovers and reconnects a camera you just put to sleep.

after setDeviceSleeping(true), isDeviceSleeping = false
>>> SILENT NO-OP: sleep never recorded

Why just recording the flag is not the fix

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. 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:

Design Does not undo own sleep Never permanently invisible
current — flag never set
always ignore while flagged
ignore inside a timed window
clear only after observed silence
suppress auto-reconnect only

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 scheduleReconnectIfNeeded and 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

…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
kmatzen force-pushed the fix/packet-reassembly branch from 372aafd to 2f8cee9 Compare July 19, 2026 04:45
@kmatzen
kmatzen force-pushed the fix/sleep-visibility branch from 3422467 to 303e745 Compare July 19, 2026 04:48
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