فهرست منبع

Fixes to better handle Omnipod comms optimizations with unreliable comms (#88)

+ Add non-persistent deliveryStatusVerified & lastCommsOK PodState vars
+ Rework updateDeliveryStatus() to handle inconsistent bolus and temp
  basal delivery status cases for both types of pod responses
+ Skip bolus comms optimizations for manual boluses, if there was a
  comms issue, or if last delivery status wasn't successfully verified
Joe Moran 4 سال پیش
والد
کامیت
2f49f523b9

+ 12 - 3
Dependencies/rileylink_ios/OmniKit/PumpManager/OmnipodPumpManager.swift

@@ -1408,9 +1408,18 @@ extension OmnipodPumpManager: PumpManager {
                 }
             }
 
-            var getStatusNeeded = true
+            var getStatusNeeded = false // initializing to true effectively disables the bolus comms getStatus optimization
             var finalizeFinishedDosesNeeded = false
-            if let unfinalizedBolus = self.state.podState?.unfinalizedBolus {
+
+            // Skip the getStatus comms optimization for a manual bolus,
+            // if there was a comms issue on the last message sent, or
+            // if the last delivery status hasn't been verified
+            if automatic == false || self.state.podState?.lastCommsOK == false ||
+                self.state.podState?.deliveryStatusVerified == false
+            {
+                self.log.info("enactBolus: skipping getStatus comms optimization")
+                getStatusNeeded = true
+            } else if let unfinalizedBolus = self.state.podState?.unfinalizedBolus {
                 if unfinalizedBolus.scheduledCertainty == .uncertain {
                     self.log.info("enactBolus: doing getStatus with uncertain bolus scheduled certainty")
                     getStatusNeeded = true
@@ -1419,7 +1428,7 @@ extension OmnipodPumpManager: PumpManager {
                     completion(.failure(PumpManagerError.deviceState(PodCommsError.unfinalizedBolus)))
                     return
                 } else if unfinalizedBolus.isBolusPositivelyFinished == false {
-                    self.log.info("enactBolus: doing getStatus to verify if bolus completion")
+                    self.log.info("enactBolus: doing getStatus to verify bolus completion")
                     getStatusNeeded = true
                 } else {
                     finalizeFinishedDosesNeeded = true // call finalizeFinishDoses() to clean up the certain & positively finalized bolus

+ 2 - 0
Dependencies/rileylink_ios/OmniKit/PumpManager/PodCommsSession.swift

@@ -228,6 +228,7 @@ public class PodCommsSession {
 
             let message = Message(address: podState.address, messageBlocks: blocksToSend, sequenceNum: messageNumber, expectFollowOnMessage: expectFollowOnMessage)
 
+            self.podState.lastCommsOK = false // mark last comms as not OK until we get the expected response
             let response = try transport.sendMessage(message)
             
             // Simulate fault
@@ -236,6 +237,7 @@ public class PodCommsSession {
 
             if let responseMessageBlock = response.messageBlocks[0] as? T {
                 log.info("POD Response: %@", String(describing: responseMessageBlock))
+                self.podState.lastCommsOK = true // message successfully sent and expected response received
                 return responseMessageBlock
             }
 

+ 26 - 7
Dependencies/rileylink_ios/OmniKit/PumpManager/PodState.swift

@@ -95,6 +95,10 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl
     
     public var insulinType: InsulinType
     
+    // the following two vars are not persistent across app restarts
+    public var deliveryStatusVerified: Bool
+    public var lastCommsOK: Bool
+
     public init(address: UInt32, piVersion: String, pmVersion: String, lot: UInt32, tid: UInt32, packetNumber: Int = 0, messageNumber: Int = 0, insulinType: InsulinType) {
         self.address = address
         self.nonceState = NonceState(lot: lot, tid: tid)
@@ -112,6 +116,8 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl
         self.setupProgress = .addressAssigned
         self.configuredAlerts = [.slot7: .waitingForPairingReminder]
         self.insulinType = insulinType
+        self.deliveryStatusVerified = false
+        self.lastCommsOK = false
     }
     
     public var unfinishedPairing: Bool {
@@ -171,19 +177,15 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl
     }
 
     public mutating func updateFromStatusResponse(_ response: StatusResponse) {
-        if unfinalizedBolus == nil && response.deliveryStatus.bolusing && response.podProgressStatus.readyForDelivery {
-            // Create the unfinalizedBolus since we currently bolusing in a ready state (possible Loop restart)
-            unfinalizedBolus = UnfinalizedDose(bolusAmount: response.bolusNotDelivered, startTime: Date(), scheduledCertainty: .certain, insulinType: insulinType, automatic: nil)
-        }
         let now = updatePodTimes(timeActive: response.timeActive)
-        updateDeliveryStatus(deliveryStatus: response.deliveryStatus)
+        updateDeliveryStatus(deliveryStatus: response.deliveryStatus, podProgressStatus: response.podProgressStatus, bolusNotDelivered: response.bolusNotDelivered)
         lastInsulinMeasurements = PodInsulinMeasurements(insulinDelivered: response.insulin, reservoirLevel: response.reservoirLevel, setupUnitsDelivered: setupUnitsDelivered, validTime: now)
         activeAlertSlots = response.alerts
     }
 
     public mutating func updateFromDetailedStatusResponse(_ response: DetailedStatus) {
         let now = updatePodTimes(timeActive: response.timeActive)
-        updateDeliveryStatus(deliveryStatus: response.deliveryStatus)
+        updateDeliveryStatus(deliveryStatus: response.deliveryStatus, podProgressStatus: response.podProgressStatus, bolusNotDelivered: response.bolusNotDelivered)
         lastInsulinMeasurements = PodInsulinMeasurements(insulinDelivered: response.totalInsulinDelivered, reservoirLevel: response.reservoirLevel, setupUnitsDelivered: setupUnitsDelivered, validTime: now)
         activeAlertSlots = response.unacknowledgedAlerts
     }
@@ -204,7 +206,21 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl
         }
     }
     
-    private mutating func updateDeliveryStatus(deliveryStatus: DeliveryStatus) {
+    private mutating func updateDeliveryStatus(deliveryStatus: DeliveryStatus, podProgressStatus: PodProgressStatus, bolusNotDelivered: Double) {
+
+        deliveryStatusVerified = true
+        // See if the pod deliveryStatus indicates an active bolus or temp basal that the PodState isn't tracking (possible Loop restart)
+        if deliveryStatus.bolusing && unfinalizedBolus == nil { // active bolus that Loop doesn't know about?
+            deliveryStatusVerified = false // remember that we had inconsistent (bolus) delivery status
+            if podProgressStatus.readyForDelivery {
+                // Create an unfinalizedBolus with the remaining bolus amount to capture what we can.
+                unfinalizedBolus = UnfinalizedDose(bolusAmount: bolusNotDelivered, startTime: Date(), scheduledCertainty: .certain, insulinType: insulinType, automatic: nil)
+            }
+        }
+        if deliveryStatus.tempBasalRunning && unfinalizedTempBasal == nil { // active temp basal that Loop doesn't know about?
+            deliveryStatusVerified = false // remember that we had inconsistent (temp basal) delivery status
+        }
+
         finalizeFinishedDoses()
 
         if let bolus = unfinalizedBolus, bolus.scheduledCertainty == .uncertain {
@@ -395,6 +411,9 @@ public struct PodState: RawRepresentable, Equatable, CustomDebugStringConvertibl
         } else {
             insulinType = .humalog
         }
+
+        self.deliveryStatusVerified = false
+        self.lastCommsOK = false
     }
     
     public var rawValue: RawValue {