Skip to content

Backport dev to next-dev: #171, #183, #185, #186, #190 - #191

Merged
ps2 merged 7 commits into
next-devfrom
backport-dev-to-next-dev-PR-171-183-185-186-190
Oct 13, 2026
Merged

ps2 merged 7 commits into
next-devfrom
backport-dev-to-next-dev-PR-171-183-185-186-190

Conversation

@ps2

@ps2 ps2 commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Brings the OmnipodKit dev PRs that next-dev is still missing into next-dev, together with #190 (background connect-on-demand for InPlay pods on iPhone 16/17e), so that #190 lands on next-dev first.

Each commit is a cherry-pick -x of the dev commit, in dev order:

dev PR commit conflicts
#171 Localize the pod tab colors 1537d11 Localizable.xcstrings: kept both "blue" and next-dev's "Bluetooth error"
#183 Give up promptly when a pod cannot be reached ca551f2 none
#186 No state updates to the delegate after deactivation (2 commits) 8b4ee3f, ae30eb4 none
#185 Persist a pod alert acknowledgment before the session runs c49f396 adapted, see below
#190 Connect on demand in the background for InPlay pods on iPhone 16/17e (2 commits) a3fd87c, f85f528 none

I compared every other dev code PR with next-dev, and all of them are already there through earlier backports (#168, #181 and others). The dev-only lokalise translation commits are left out.

#185 on next-dev

On next-dev, acknowledgeAlert is async and already retries once (#182), so I folded #185's behavior into that version instead of using dev's completion-based code:

  • The alert is added to alertsWithPendingAcknowledgment before the first attempt, so an app that dies mid-session still clears the pod alert on the next status update. Previously next-dev only recorded it after both attempts had failed.
  • acknowledgeAlertSlots(_:for:) checks when its session actually runs whether the alert is still pending. If not, it skips the 0x11, which avoids the duplicate acknowledge seen on dev. It removes the alert from the pending set on success.
  • silenceAcknowledgedAlerts gets the same check, unchanged from dev.
  • One edge case: if the silenceAcknowledgedAlerts retry clears an expiry alert first, it only acknowledges the triggering slot. The expiration-reminder slot that next-dev's acknowledgeAlert adds would then wait for the pod's own handling.

Testing

marionbarker and others added 7 commits October 12, 2026 14:15
* Give up promptly when an on-demand connect fails

The retry added in #174 fired whenever the peripheral was not connected
after the first attempt, so a connect that simply timed out paid a
second 45 s wait and logged a misleading "link dropped after
connecting". Only retry when the link was actually up and then dropped.

Sessions run on a serial queue and each one waited on its own connect,
so a deactivate queued behind a loop cycle and a status refresh spent
minutes rediscovering the same unreachable pod. A session now skips the
connect if one already failed after it was enqueued, so everything
waiting behind a failed connect fails at once. A session enqueued after
the failure, such as a Retry tap, gets a fresh attempt.

* Wait 20 s for an on-demand connect when the eager watchdog is not in play

The 45 s connect timeout exists to sit above the eager watchdog's 40 s
budget on InPlay-affected phones. Everywhere else a nearby pod connects
in about a second and an absent pod never does, so the long wait only
delays the failure the user is about to see.

* Say what the deactivation is waiting on under the spinner

A bare indeterminate spinner for the length of a connect timeout reads
as a hang; one user deleted the app rather than wait it out. Show
"Connecting to pod" at once and "The pod is not responding. Still
trying" after ten seconds, cleared when the attempt finishes.

* update string catalog

---------

Co-authored-by: marionbarker <marionbarker@earthlink.net>
(cherry picked from commit 94f2a17)
Stop Using released the RileyLinks and then asked the delegate to remove the
pump manager. The RileyLink disconnects run asynchronously on the device
provider's queue and each one writes the new connection state into
OmniPumpManagerState, which queues pumpManagerDidUpdateState. Those calls
usually land after pumpManagerWillDeactivate. Trio's DeviceDataManager
re-adopts a pump manager passed to pumpManagerDidUpdateState when it has none,
so after leaving OmnipodKit with a RileyLink it could show "No Pod" instead of
"Add Pump".

Add stopUsing(completion:), which sets a flag before releasing Bluetooth and
notifying the delegate. While the flag is set, state changes are still applied
but no longer reported to the delegate or status observers.

(cherry picked from commit 58658ba)
* Persist a pod alert acknowledgment before the session runs

Loop records an alert as acknowledged the moment it is tapped, whether or not
the pump manager manages to tell the pod. OmnipodKit only remembered the
acknowledgment in alertsWithPendingAcknowledgment after the "Acknowledge Alert"
session had run and failed. With connect-on-demand that session can sit behind
other queued sessions for a minute or more waiting on a connect, and if the app
is killed in that window nothing survives: Loop has nothing left to show, the
pod keeps beeping, and no retry is ever attempted.

Insert the alert into the persisted pending set before starting the session and
remove it only once the pod confirms. silenceAcknowledgedAlerts already retries
that set on every status update, so a kill mid-session now clears the pod alert
at the next pod contact.

* Send one acknowledge per pod alert when sessions overlap

silenceAcknowledgedAlerts reads the pending set when it is called and queues a
session. Two callers close together, such as the keep-alive status read and a
loop cycle right after launch, each queued one, so the pod got the same 0x11
twice. With the alert now in the pending set while the user's acknowledge is
queued, an overlapping status session could also send a retry next to it.

Sessions run serially, so check the pending set again inside each session and
skip the command if another session has already cleared the alert.

(cherry picked from commit 3e80ce6)

Adapted for next-dev's async acknowledgeAlert: the pending acknowledgment is persisted before the first attempt, the retry from #182 is kept, and acknowledgeAlertSlots skips the command when the alert is no longer pending.
InPlay pods on iPhone 16/17e were held connected while Loop was in the
background: shouldHoldConnection returned true for any eager-gated pod,
background connects asked the system to auto-reconnect, and the idle
disconnect waited an hour. Users on these combos are seeing 0xCB (203)
pod faults, which we attribute to the held link.

The background now uses connect-on-demand on every phone/pod combo: the
short idle disconnect, the alarm scan and the StartDelay heartbeat probe.
The eager watchdog still supervises each connect, and the foreground
keep-alive is unchanged.

Pod Keep Alive Silent Tune and RileyLink still hold the link in the
background, since users choose those modes. The auto-reconnect standing
connect and the drop-driven heartbeat now apply only under those modes,
and the degraded-heartbeat notice only shows then.

Going to the background now cancels an in-flight eager connect, so it
disarms the watchdog first; otherwise the watchdog re-issued it.

Removes the OmnipodKit.eagerIdleDisconnectSeconds setting.

(cherry picked from commit a8ff32e)
A session only counted as active once its connect had finished, because
beginCommandSession ran inside the session block, after configureAndRun
connects. Backgrounding while a bolus waited on its connect let
enterBackground cancel that connect; nothing re-issued it, so the session
waited out the connect timeout and the bolus failed without being sent.
That gap existed for all pods, and #190 extended it to InPlay pods on
iPhone 16/17e, which no longer hold the link in the background.

Count the session when it is queued instead, so enterBackground defers
the disconnect until the session is done.

(cherry picked from commit a5d63a0)
@marionbarker

marionbarker commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Test

✅ confirm updated behavior from

  • PR 171 - code inspection
  • PR 183 - test
  • PR 185 - test
  • PR 190 - code inspection (diffs are the same)

edited to add

  • PR 186 - code inspection

Configuration

Start with LoopWorkspace next-dev, commit a2c9964.
Point to OmnipodKit branch backport-dev-to-next-dev-PR-171-183-185-186-190, commit f85f528

Build onto SE 3rd gen running iOS 27.0.1 connected to rPi DASH using Nightscout as CGM

Test Details

Tests were performed on 2026-10-12. Local times are PDT (-7 UTC).
Initial condition - PKA still set to Silent Tune following tests from PR 190.

Build launched at 14:12

Repeat the alert test from PR 185

  • Different behavior because this is next-dev
  • Following a quit/restart, the Low Reservoir alert shows up again on the main screen
  • acknowledge it and then restart the rPi
  • one, and only one 0x11 command is issued
    • alerts_bit_mask in the 0x1d response changed from 16 before to 0 after the 0x11 command

Repeat the shorter response time for Deactivate when pod not connected from PR 183

  • quit out of rPi
  • get same 10 sec plus 10 sec timing for the two messages followed by option to Discard Pod

@marionbarker marionbarker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve by test and comparison of code to dev changes.

@ps2

ps2 commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Test results on next-dev: iPhone 16 Pro + InPlay pod

Build: LoopWorkspace next-dev a2c9964 (LoopKit/LoopWorkspace#531) with OmnipodKit at this PR's head (f85f528), built with the LoopWorkspace scheme and installed on the phone. It's the same pod (178BA002) used for the #190 results, looping with a G7. No Pod Keep Alive mode. Window: 14:58–17:03, 124 min (about 120 min background, 5 min foreground). Numbers come from the OmnipodKit device log.

Reliability

  • 45 commands sent, 45 replies. The log has no comms errors, faults or pod alerts.
  • 19 of 21 connects succeeded. Two gave up:
    • 15:12: a foreground pre-connect gave up after about 42 s, and the app went to the background during it. No command was waiting, and the next cycle connected at 15:15.
    • 15:45: a background connect retried for about 45 s, and the queued command then failed fast (queued behind a failed connect — failing fast, Give up promptly when a pod cannot be reached #183). Opening the app connected in 5 s and read status. The 15:50 cycle was normal. This is the only cycle that may have missed the pod.
  • Otherwise no missed cycles. The pod was skipped on some readings only because its status was still under 6 minutes old (isPumpDataStale) and no new temp basal was needed.

Connect time

From "command connect" to "Pod connected", for the 19 successful connects:

n median worst first-try
19 10.3 s 38.0 s 2

Most connects hit the wedge at least once, with a cancel/retry about every 2.2–2.5 s, the same as on dev. About one in three took 15–38 s.

Background connection duty cycle

connected connected + connecting
1.6% (114 s of 120 min) 7.7%

Each background cycle connects, sends its commands, and disconnects about 5 s after the last reply. The link was never held in the background.

Backgrounding mid-command (f85f528)

The deferral fired 3 times (background — command in flight, deferring disconnect). Each time, the connect finished or was given up cleanly, any command was delivered, and the disconnect followed.

Not exercised in this window

@ps2
ps2 merged commit 94a412d into next-dev Oct 13, 2026
ps2 added a commit to LoopKit/LoopWorkspace that referenced this pull request Oct 13, 2026
Pins each submodule to its base branch tip, which is the merge commit of its plugin picker PR. Also picks up the other PRs merged since the last bump: LoopKit #641, #643 and #645; Loop #2570 and #2573; loopandlearn/OmnipodKit#191; G7SensorKit #93; and the warning cleanups.
ps2 added a commit to LoopKit/LoopWorkspace that referenced this pull request Oct 13, 2026
…les) (#532)

* Pin the plugin picker subtitle branches

Points the 17 submodules at their plugin-picker-subtitle branches (Camji55's manufacturer field PRs merged onto the current base, plus the picker subtitle), so CI builds and tests them together.

* Bump submodules to the merged plugin picker PRs

Pins each submodule to its base branch tip, which is the merge commit of its plugin picker PR. Also picks up the other PRs merged since the last bump: LoopKit #641, #643 and #645; Loop #2570 and #2573; loopandlearn/OmnipodKit#191; G7SensorKit #93; and the warning cleanups.
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.

3 participants