Просмотр исходного кода

management of manual temp basal

avouspierre 3 лет назад
Родитель
Сommit
e74daabc83

+ 33 - 0
FreeAPS/Resources/Assets.xcassets/Colors/warning.colorset/Contents.json

@@ -0,0 +1,33 @@
+{
+  "colors" : [
+    {
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "alpha" : "1.000",
+          "blue" : "0.269",
+          "green" : "0.763",
+          "red" : "0.917"
+        }
+      },
+      "idiom" : "universal"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "color" : {
+        "platform" : "ios",
+        "reference" : "systemYellowColor"
+      },
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 27 - 0
FreeAPS/Sources/APS/APSManager.swift

@@ -2,6 +2,7 @@ import Combine
 import Foundation
 import LoopKit
 import LoopKitUI
+import OmniBLE
 import RileyLinkKit
 import SwiftDate
 import Swinject
@@ -19,6 +20,7 @@ protocol APSManager {
     var lastLoopDateSubject: PassthroughSubject<Date, Never> { get }
     var bolusProgress: CurrentValueSubject<Decimal?, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
+    var isManualTempBasal: Bool { get }
     func enactTempBasal(rate: Double, duration: TimeInterval)
     func makeProfiles() -> AnyPublisher<Bool, Never>
     func determineBasal() -> AnyPublisher<Bool, Never>
@@ -36,6 +38,7 @@ enum APSError: LocalizedError {
     case apsError(message: String)
     case deviceSyncError(message: String)
     case deviceAlert(message: String)
+    case manualBasalTemp(message: String)
 
     var errorDescription: String? {
         switch self {
@@ -51,6 +54,8 @@ enum APSError: LocalizedError {
             return "Sync error: \(message)"
         case let .deviceAlert(message):
             return "Pump message: \(message)"
+        case let .manualBasalTemp(message):
+            return "Manual Basal Temp : \(message)"
         }
     }
 }
@@ -85,6 +90,8 @@ final class BaseAPSManager: APSManager, Injectable {
 
     var bluetoothManager: BluetoothStateManager? { deviceDataManager.bluetoothManager }
 
+    var isManualTempBasal: Bool = false
+
     let isLooping = CurrentValueSubject<Bool, Never>(false)
     let lastLoopDateSubject = PassthroughSubject<Date, Never>()
     let lastError = CurrentValueSubject<Error?, Never>(nil)
@@ -146,6 +153,21 @@ final class BaseAPSManager: APSManager, Injectable {
                 }
             }
             .store(in: &lifetime)
+
+        // manage a manual Temp Basal from OmniPod - Force loop() after stop a temp basal or finished
+        deviceDataManager.manualTempBasal
+            .receive(on: processQueue)
+            .sink { manualBasal in
+                if manualBasal {
+                    self.isManualTempBasal = true
+                } else {
+                    if self.isManualTempBasal {
+                        self.isManualTempBasal = false
+                        self.loop()
+                    }
+                }
+            }
+            .store(in: &lifetime)
     }
 
     func heartbeat(date: Date) {
@@ -221,6 +243,11 @@ final class BaseAPSManager: APSManager, Injectable {
             return APSError.invalidPumpState(message: "Pump suspended")
         }
 
+        // block all if manual temp basal
+        if isManualTempBasal {
+            return APSError.manualBasalTemp(message: "Unable to change anything")
+        }
+
         let reservoir = storage.retrieve(OpenAPS.Monitor.reservoir, as: Decimal.self) ?? 100
         guard reservoir > 0 else {
             return APSError.invalidPumpState(message: "Reservoir is empty")

+ 25 - 0
FreeAPS/Sources/APS/DeviceDataManager.swift

@@ -18,6 +18,7 @@ protocol DeviceDataManager: GlucoseSource {
     var pumpDisplayState: CurrentValueSubject<PumpDisplayState?, Never> { get }
     var recommendsLoop: PassthroughSubject<Void, Never> { get }
     var bolusTrigger: PassthroughSubject<Bool, Never> { get }
+    var manualTempBasal: PassthroughSubject<Bool, Never> { get }
     var errorSubject: PassthroughSubject<Error, Never> { get }
     var pumpName: CurrentValueSubject<String, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
@@ -63,6 +64,7 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
     let bolusTrigger = PassthroughSubject<Bool, Never>()
     let errorSubject = PassthroughSubject<Error, Never>()
     let pumpNewStatus = PassthroughSubject<Void, Never>()
+    let manualTempBasal = PassthroughSubject<Bool, Never>()
     var alertStore: [Alert]
     @SyncAccess private var pumpUpdateCancellable: AnyCancellable?
     private var pumpUpdatePromise: Future<Bool, Never>.Promise?
@@ -330,6 +332,17 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
                 $0.pumpReservoirDidChange(Decimal(reservoir))
             }
 
+            if let tempBasal = omnipod.state.podState?.unfinalizedTempBasal, !tempBasal.isFinished(),
+               !tempBasal.automatic
+            {
+                // the manual basal temp is launch - block every thing
+                debug(.deviceManager, "manual temp basal")
+                manualTempBasal.send(true)
+            } else {
+                // no more manual Temp Basal !
+                manualTempBasal.send(false)
+            }
+
             guard let endTime = omnipod.state.podState?.expiresAt else {
                 pumpExpiresAtDate.send(nil)
                 return
@@ -347,6 +360,18 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
                 $0.pumpReservoirDidChange(Decimal(reservoir))
             }
 
+            // manual temp basal on
+            if let tempBasal = omnipodBLE.state.podState?.unfinalizedTempBasal, !tempBasal.isFinished(),
+               !tempBasal.automatic
+            {
+                // the manual basal temp is launch - block every thing
+                debug(.deviceManager, "manual temp basal")
+                manualTempBasal.send(true)
+            } else {
+                // no more manual Temp Basal !
+                manualTempBasal.send(false)
+            }
+
             guard let endTime = omnipodBLE.state.podState?.expiresAt else {
                 pumpExpiresAtDate.send(nil)
                 return

+ 16 - 6
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -140,12 +140,22 @@ extension Home {
                         .font(.system(size: 12, weight: .bold)).foregroundColor(.loopGray)
                         .padding(.leading, 8)
                 } else if let tempRate = state.tempRate {
-                    Text(
-                        (numberFormatter.string(from: tempRate as NSNumber) ?? "0") +
-                            NSLocalizedString(" U/hr", comment: "Unit per hour with space")
-                    )
-                    .font(.system(size: 12, weight: .bold)).foregroundColor(.insulin)
-                    .padding(.leading, 8)
+                    if state.apsManager.isManualTempBasal {
+                        Text(
+                            (numberFormatter.string(from: tempRate as NSNumber) ?? "0") +
+                                NSLocalizedString(" U/hr", comment: "Unit per hour with space") +
+                                NSLocalizedString(" -  Manual Basal ⚠️", comment: "Manual Temp basal")
+                        )
+                        .font(.system(size: 12, weight: .bold)).foregroundColor(.insulin)
+                        .padding(.leading, 8)
+                    } else {
+                        Text(
+                            (numberFormatter.string(from: tempRate as NSNumber) ?? "0") +
+                                NSLocalizedString(" U/hr", comment: "Unit per hour with space")
+                        )
+                        .font(.system(size: 12, weight: .bold)).foregroundColor(.insulin)
+                        .padding(.leading, 8)
+                    }
                 }
 
                 if let tempTarget = state.tempTarget {