Skip to content

Smartwatch manager for loop - #2646

Open
dabear wants to merge 7 commits into
LoopKit:next-devfrom
bjorninge-no-personal:smartwatch-manager-review
Open

dabear wants to merge 7 commits into
LoopKit:next-devfrom
bjorninge-no-personal:smartwatch-manager-review

Conversation

@dabear

@dabear dabear commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Loop: host SmartwatchManager plugins

Hosts the new watch plugin type from LoopKit LoopKit/LoopKit#684. Full description, screenshots and reviewer questions: LoopKit/LoopWorkspace#569, which also adds the first plugin (Pebble).

Part of three PRs: LoopKit LoopKit/LoopKit#684, Loop (this), and LoopWorkspace LoopKit/LoopWorkspace#569.

Commits

Commit What
36bc837d bluetooth-peripheral background mode through Info.plist preprocessing (LOOP_BLUETOOTH_PERIPHERAL, on by default; cleared in LoopConfigOverride.xcconfig to leave it out).
19e32506 Host SmartwatchManager plugins: one watch under Settings → Devices → Add Watch, saved and restored like the pump and CGM; SmartwatchManagerHost snapshots; glucose alerts through a new AlertForwarder hook on AlertManager, following Loop's mute; the plugin's log lines and device alerts; unhandled URLs offered to the plugin.
e3425e1d Remote actions from watch plugins: each behind its own Watch Permissions toggle, off by default, checked with LoopKit's rules. The Pebble plugin declares none, so the screen stays hidden. Revert it together with 647c0dd4 (its strings) to leave remote actions out.
47e7c4ab The host's new strings in Loop/Localizable.xcstrings (the Watch row and picker, the device alert's OK button, preset names sent to a watch), as Xcode extracts them, so they reach translation.
647c0dd4 The remote actions' strings in the string catalog: Watch Permissions, its toggles and their footers.
097ada11 Settings: make clear that Add Watch is for watches other than Apple Watch. The Devices row says so, the watch picker says that Loop's Apple Watch app is installed from the Watch app, and the picker's fallback icon is a generic watch.
6c4ee8ff Merge next-dev. The watch host now imports LoopCore for LoopConstants, which moved there (#2645). Reverting e3425e1d after this merge conflicts on SmartwatchManagerHost+RemoteActions.swift: delete the file.

Testing

  • LoopTests pass in both versions: 431 without remote actions, 432 with (three upstream string tests need a US region: -testRegion US).
  • Used daily on an iPhone with a Pebble Time 2: setup, reconnects, unit changes, alerts.

Bjørn Inge added 3 commits November 2, 2026 11:27
Watch plugins that publish a Bluetooth service, such as a Pebble plugin, need
the bluetooth-peripheral background mode to keep the watch updated while Loop
is in the background, and a plugin bundle can't declare background modes
itself. Info.plist lists it under #if LOOP_BLUETOOTH_PERIPHERAL, defined in
Loop.xcconfig; clearing INFOPLIST_PREPROCESSOR_DEFINITIONS (for example in
LoopConfigOverride.xcconfig) leaves it out. The built Info.plist is otherwise
unchanged.
One watch plugin, under Settings → Devices → Add Watch, saved and restored like the pump and CGM.

- `SmartwatchManagerHost` sends snapshots when a reading is stored and when the loop's output changes, with only what the plugin declares and requests: glucose, history, prediction, loop status and therapy context.
- Glucose alerts reach the watch through a new `AlertForwarder` hook on `AlertManager`, following Loop's mute. Test alerts show on the watch and clear after 30 s; alarms that are off in the active profile, or all while the CGM raises its own, are cleared on the watch.
- The plugin's log lines go to the device log, and its device alerts become Loop alerts, at most time-sensitive.
- URLs Loop doesn't handle are offered to the plugin.
Bolus, carbs, alert mute and override presets requested from the watch, each behind its own Watch Permissions toggle, off by default, and checked with LoopKit's `SmartwatchRemoteActionPolicy`. The screen shows only when the plugin declares a remote action; the Pebble plugin declares none. Revert this commit to leave remote actions out.

- Bolus: through the remote bolus path (maximum bolus, notifications, upload), with the bolus context in the snapshot, recent glucose required, and the plugin's `remoteActionLimits`.
- Carbs: through the remote carbs path, dated when the user confirmed them on the watch.
- Mute: Loop's alert mute, capped at its own durations.
- Presets: Loop's override presets in the snapshot; start one or end the running one through the remote override path. Temp targets are refused (LoopKit's default).
- Deleting or replacing the watch turns every permission off.
Bjørn Inge and others added 4 commits November 2, 2026 13:38
The Watch row, the watch picker, the device alert's OK button and the preset names sent to a watch, added to Loop/Localizable.xcstrings as Xcode extracts them, so they reach translation. Custom Preset is in use again, with its translations.
Watch Permissions, its toggles and their footers, added to Loop/Localizable.xcstrings as Xcode extracts them. Revert this commit together with "Remote actions from watch plugins" to leave remote actions out.
…atch

Loop's Apple Watch app needs no setup in Settings → Devices, so people looking for it there would find only other watches. The Devices row now reads "Tap here to set up a watch other than Apple Watch", and the watch picker says that Apple Watch isn't added there and where Loop's Apple Watch app comes from. The picker's fallback icon for a watch plugin is a generic watch instead of the Apple Watch symbol. The string catalog follows.
…ore)

The watch host imports LoopCore for LoopConstants, which moved there (LoopKit#2645).
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