From cce7badf9663d29176c3c809e06a19fd68e918ce Mon Sep 17 00:00:00 2001 From: marionbarker Date: Fri, 7 Feb 2025 17:12:13 -0800 Subject: [PATCH 1/3] fix for pump manager returns bogus podSuspended; * add self.tryToValidateComms to handle uncertain comms; * ensure podSuspended is only returned when actually suspended --- OmniKit/PumpManager/OmnipodPumpManager.swift | 75 +++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/OmniKit/PumpManager/OmnipodPumpManager.swift b/OmniKit/PumpManager/OmnipodPumpManager.swift index 00aebeb..d36a60e 100644 --- a/OmniKit/PumpManager/OmnipodPumpManager.swift +++ b/OmniKit/PumpManager/OmnipodPumpManager.swift @@ -1003,6 +1003,33 @@ extension OmnipodPumpManager { } } + // Will execute a getStatus command if the pod is not connected, the last delivery statusreceived is invalid, + // or there is an unacknowledged command. If the getStatus fails, returns its error that can be passed on the + // higher level instead of having to return a potentially inappropriate error when using uncertain pod status. + // Returns nil if comms looks OK or a getStatus was successful executed or the getStatus error on failure. + private func tryToValidateComms(session: PodCommsSession) -> LocalizedError? { + + // If we're connected, have a valid delivery status, and there is not an unacknowledged command, we're all good to go + if state.rileyLinkConnectionManagerState != nil && self.state.podState?.lastDeliveryStatusReceived != nil && self.state.podState?.unacknowledgedCommand == nil { + return nil + } + + // Attempt to do a getStatus to try to resolve any outstanding comms issues + do { + let _ = try session.getStatus() + // Paranoid debug testing as the successful getStatus should have set the last delivery status and handled any unacknowledged command. + if self.state.podState?.lastDeliveryStatusReceived == nil || self.state.podState?.unacknowledgedCommand != nil { + self.log.error("### tryToValidateComms getStatus successful, but still have no last delivery status or an unacknowledged command!") + } else { + self.log.debug("### tryToValidateComms getStatus resolved all pending comms issues") + } + return nil + } catch let error { + self.log.debug("### tryToValidateComms getStatus failed, returning: %@", error.localizedDescription) + return error as? LocalizedError + } + } + // MARK: - Pump Commands public func getPodStatus(completion: ((_ result: PumpManagerResult) -> Void)? = nil) { @@ -1119,6 +1146,11 @@ extension OmnipodPumpManager { switch result { case .success(let session): do { + if let error = self.tryToValidateComms(session: session) { + completion(.state(error)) + return + } + let beep = self.silencePod ? false : self.beepPreference.shouldBeepForManualCommand let _ = try session.setTime(timeZone: timeZone, basalSchedule: self.state.basalSchedule, date: Date(), acknowledgementBeep: beep) self.setState { (state) in @@ -1171,6 +1203,11 @@ extension OmnipodPumpManager { do { switch result { case .success(let session): + if let error = self.tryToValidateComms(session: session) { + completion(error) + return + } + let scheduleOffset = timeZone.scheduleOffset(forDate: Date()) let result = session.cancelDelivery(deliveryType: .all) switch result { @@ -1415,6 +1452,11 @@ extension OmnipodPumpManager { self.podComms.runSession(withName: name, using: rileyLinkSelector) { (result) in switch result { case .success(let session): + if let error = self.tryToValidateComms(session: session) { + completion(.communication(error)) + return + } + // enable/disable Pod completion beep state for any unfinalized manual insulin delivery let enabled = newPreference.shouldBeepForManualCommand let beepType: BeepType = enabled ? .bipBip : .noBeepNonCancel @@ -1466,6 +1508,11 @@ extension OmnipodPumpManager { return } + if let error = self.tryToValidateComms(session: session) { + completion(.state(error)) + return + } + guard let configuredAlerts = self.state.podState?.configuredAlerts, let activeAlertSlots = self.state.podState?.activeAlertSlots, let reservoirLevel = self.state.podState?.lastInsulinMeasurements?.reservoirLevel?.rawValue else @@ -1716,6 +1763,11 @@ extension OmnipodPumpManager: PumpManager { state.suspendEngageState = .engaging }) + if let error = self.tryToValidateComms(session: session) { + completion(error) + return + } + // Use a beepBlock for the confirmation beep to avoid getting 3 beeps using cancel command beeps! let beepBlock = self.beepMessageBlock(beepType: .beeeeeep) let result = session.suspendDelivery(suspendReminder: suspendReminder, silent: self.silencePod, beepBlock: beepBlock) @@ -1762,6 +1814,11 @@ extension OmnipodPumpManager: PumpManager { state.suspendEngageState = .disengaging }) + if let error = self.tryToValidateComms(session: session) { + completion(error) + return + } + do { let scheduleOffset = self.state.timeZone.scheduleOffset(forDate: Date()) let beep = self.silencePod ? false : self.beepPreference.shouldBeepForManualCommand @@ -1870,7 +1927,14 @@ extension OmnipodPumpManager: PumpManager { state.bolusEngageState = .engaging }) - guard let podState = self.state.podState, !podState.isSuspended && podState.lastDeliveryStatusReceived?.suspended == false else { + if let error = self.tryToValidateComms(session: session) { + completion(.deviceState(error)) + return + } + + // Use a lastDeliveryStatusReceived?.suspended != true test here to not return a pod suspended failure if + // there is not a valid last delivery status (which shouldn't even happen now with tryToValidateComms()). + guard let podState = self.state.podState, !podState.isSuspended && podState.lastDeliveryStatusReceived?.suspended != true else { self.log.info("Not enacting bolus because podState or last status received indicates pod is suspended") completion(.deviceState(PodCommsError.podSuspended)) return @@ -2009,7 +2073,14 @@ extension OmnipodPumpManager: PumpManager { return } - guard let podState = self.state.podState, !podState.isSuspended && podState.lastDeliveryStatusReceived?.suspended == false else { + if let error = self.tryToValidateComms(session: session) { + completion(.deviceState(PumpManagerError.deviceState(error))) + return + } + + // Use a lastDeliveryStatusReceived?.suspended != true test here to not return a pod suspended failure if + // there is not a valid last delivery status (which shouldn't even happen now with tryToValidateComms()). + guard let podState = self.state.podState, !podState.isSuspended && podState.lastDeliveryStatusReceived?.suspended != true else { self.log.info("Not enacting temp basal because podState or last status received indicates pod is suspended") completion(.deviceState(PodCommsError.podSuspended)) return From 9d9d499cddf27c1fa8a95541f23f0e549faf53a1 Mon Sep 17 00:00:00 2001 From: marionbarker Date: Sun, 9 Feb 2025 21:06:36 -0800 Subject: [PATCH 2/3] remove an unneeded connection check, revise some comments and remove extra debug logging --- OmniKit/PumpManager/OmnipodPumpManager.swift | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/OmniKit/PumpManager/OmnipodPumpManager.swift b/OmniKit/PumpManager/OmnipodPumpManager.swift index d36a60e..d850a7b 100644 --- a/OmniKit/PumpManager/OmnipodPumpManager.swift +++ b/OmniKit/PumpManager/OmnipodPumpManager.swift @@ -1003,26 +1003,20 @@ extension OmnipodPumpManager { } } - // Will execute a getStatus command if the pod is not connected, the last delivery statusreceived is invalid, - // or there is an unacknowledged command. If the getStatus fails, returns its error that can be passed on the - // higher level instead of having to return a potentially inappropriate error when using uncertain pod status. - // Returns nil if comms looks OK or a getStatus was successful executed or the getStatus error on failure. + // If the last delivery status received is invalid or there is an unacknowledged command, execute a getStatus command + // for the current PodCommsSession. If the getStatus fails, return its error to be passed on to the higher level. + // Return nil if comms looks OK or the getStatus was successful. private func tryToValidateComms(session: PodCommsSession) -> LocalizedError? { - // If we're connected, have a valid delivery status, and there is not an unacknowledged command, we're all good to go - if state.rileyLinkConnectionManagerState != nil && self.state.podState?.lastDeliveryStatusReceived != nil && self.state.podState?.unacknowledgedCommand == nil { + // Since we're already connected for this session, if we have a delivery status and no unacknowledged command, return nil + if self.state.podState?.lastDeliveryStatusReceived != nil && self.state.podState?.unacknowledgedCommand == nil { return nil } // Attempt to do a getStatus to try to resolve any outstanding comms issues do { let _ = try session.getStatus() - // Paranoid debug testing as the successful getStatus should have set the last delivery status and handled any unacknowledged command. - if self.state.podState?.lastDeliveryStatusReceived == nil || self.state.podState?.unacknowledgedCommand != nil { - self.log.error("### tryToValidateComms getStatus successful, but still have no last delivery status or an unacknowledged command!") - } else { - self.log.debug("### tryToValidateComms getStatus resolved all pending comms issues") - } + self.log.debug("### tryToValidateComms getStatus resolved all pending comms issues") return nil } catch let error { self.log.debug("### tryToValidateComms getStatus failed, returning: %@", error.localizedDescription) From 447caa4d94e8b75aa5d8b49e797eaa60da068f69 Mon Sep 17 00:00:00 2001 From: marionbarker Date: Mon, 10 Feb 2025 17:36:24 -0800 Subject: [PATCH 3/3] use correct .communication errors instead of .state or .deviceState --- OmniKit/PumpManager/OmnipodPumpManager.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OmniKit/PumpManager/OmnipodPumpManager.swift b/OmniKit/PumpManager/OmnipodPumpManager.swift index d850a7b..aba8b5e 100644 --- a/OmniKit/PumpManager/OmnipodPumpManager.swift +++ b/OmniKit/PumpManager/OmnipodPumpManager.swift @@ -1141,7 +1141,7 @@ extension OmnipodPumpManager { case .success(let session): do { if let error = self.tryToValidateComms(session: session) { - completion(.state(error)) + completion(.communication(error)) return } @@ -1503,7 +1503,7 @@ extension OmnipodPumpManager { } if let error = self.tryToValidateComms(session: session) { - completion(.state(error)) + completion(.communication(error)) return } @@ -1922,7 +1922,7 @@ extension OmnipodPumpManager: PumpManager { }) if let error = self.tryToValidateComms(session: session) { - completion(.deviceState(error)) + completion(.communication(error)) return } @@ -2068,7 +2068,7 @@ extension OmnipodPumpManager: PumpManager { } if let error = self.tryToValidateComms(session: session) { - completion(.deviceState(PumpManagerError.deviceState(error))) + completion(.communication(error)) return }