Jelajahi Sumber

CD glucose for bolus calculation

polscm32 2 tahun lalu
induk
melakukan
a09c6e9651

+ 46 - 40
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -42,7 +42,6 @@ extension Bolus {
         var waitForSuggestionInitial: Bool = false
         var waitForSuggestionInitial: Bool = false
 
 
         // added for bolus calculator
         // added for bolus calculator
-        @Published var recentGlucose: BloodGlucose?
         @Published var target: Decimal = 0
         @Published var target: Decimal = 0
         @Published var cob: Decimal = 0
         @Published var cob: Decimal = 0
         @Published var iob: Decimal = 0
         @Published var iob: Decimal = 0
@@ -93,11 +92,14 @@ extension Bolus {
         @Published var externalInsulin: Bool = false
         @Published var externalInsulin: Bool = false
         @Published var showInfo: Bool = false
         @Published var showInfo: Bool = false
 
 
+        @Published var glucoseFromPersistence: [GlucoseStored] = []
+
         let now = Date.now
         let now = Date.now
 
 
         let context = CoreDataStack.shared.persistentContainer.viewContext
         let context = CoreDataStack.shared.persistentContainer.viewContext
 
 
         override func subscribe() {
         override func subscribe() {
+            fetchGlucose()
             setupInsulinRequired()
             setupInsulinRequired()
             broadcaster.register(SuggestionObserver.self, observer: self)
             broadcaster.register(SuggestionObserver.self, observer: self)
             broadcaster.register(BolusFailureObserver.self, observer: self)
             broadcaster.register(BolusFailureObserver.self, observer: self)
@@ -139,49 +141,57 @@ extension Bolus {
             }
             }
         }
         }
 
 
+        // MARK: - Basal
+
         func getCurrentBasal() {
         func getCurrentBasal() {
             let basalEntries = provider.getProfile()
             let basalEntries = provider.getProfile()
-
+            let now = Date()
             let dateFormatter = DateFormatter()
             let dateFormatter = DateFormatter()
             dateFormatter.dateFormat = "HH:mm:ss"
             dateFormatter.dateFormat = "HH:mm:ss"
-            let currentTime = dateFormatter.string(from: Date())
 
 
-            // loop throug entries and get current basal entry
+            // iterate over basal entries
             for (index, entry) in basalEntries.enumerated() {
             for (index, entry) in basalEntries.enumerated() {
-                if let entryStartTimeDate = dateFormatter.date(from: entry.start) {
-                    var entryEndTimeDate: Date
-
-                    if index < basalEntries.count - 1 {
-                        let nextEntry = basalEntries[index + 1]
-                        if let nextEntryStartTimeDate = dateFormatter.date(from: nextEntry.start) {
-                            let timeDifference = nextEntryStartTimeDate.timeIntervalSince(entryStartTimeDate)
-                            entryEndTimeDate = entryStartTimeDate.addingTimeInterval(timeDifference)
-                        } else {
-                            continue
-                        }
-                    } else {
-                        entryEndTimeDate = Date()
-                    }
-                    // if currenTime is between start and end of basal entry -> basal = currentBasal
-                    if let currentTimeDate = dateFormatter.date(from: currentTime) {
-                        if currentTimeDate >= entryStartTimeDate, currentTimeDate <= entryEndTimeDate {
-                            if let basal = entry.rate as? Decimal {
-                                currentBasal = basal
-                                break
-                            }
-                        }
-                    }
+                guard let entryStartTime = dateFormatter.date(from: entry.start) else { continue }
+
+                let entryEndTime: Date
+                if index < basalEntries.count - 1,
+                   let nextEntryStartTime = dateFormatter.date(from: basalEntries[index + 1].start)
+                {
+                    // end of current entry should equal start of next entry
+                    entryEndTime = nextEntryStartTime
+                } else {
+                    // if it is the last entry use current time as end of entry
+                    entryEndTime = now
+                }
+
+                // proof if current time is between start and end of entry
+                if now >= entryStartTime, now < entryEndTime {
+                    currentBasal = entry.rate
+                    break
                 }
                 }
             }
             }
         }
         }
 
 
-        func getDeltaBG() {
-            let glucose = provider.fetchGlucose()
-            guard glucose.count >= 3 else { return }
-            let lastGlucose = glucose.first?.glucose ?? 0
-            let thirdLastGlucose = glucose[2]
-            let delta = Decimal(lastGlucose) - Decimal(thirdLastGlucose.glucose)
-            deltaBG = delta
+        // MARK: - Glucose
+
+        private func fetchGlucose() {
+            let fetchRequest: NSFetchRequest<GlucoseStored> = GlucoseStored.fetchRequest()
+            fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \GlucoseStored.date, ascending: false)]
+            fetchRequest.predicate = NSPredicate.predicateFor30MinAgo
+            fetchRequest.fetchLimit = 3
+            do {
+                glucoseFromPersistence = try context.fetch(fetchRequest)
+
+                let lastGlucose = glucoseFromPersistence.first?.glucose ?? 0
+                let thirdLastGlucose = glucoseFromPersistence.last?.glucose ?? 0
+                let delta = Decimal(lastGlucose) - Decimal(thirdLastGlucose)
+
+                currentBG = Decimal(lastGlucose)
+                deltaBG = delta
+
+            } catch {
+                debugPrint("Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to fetch glucose")
+            }
         }
         }
 
 
         // MARK: CALCULATIONS FOR THE BOLUS CALCULATOR
         // MARK: CALCULATIONS FOR THE BOLUS CALCULATOR
@@ -260,7 +270,6 @@ extension Bolus {
                 self.target = self.provider.suggestion?.current_target ?? 0
                 self.target = self.provider.suggestion?.current_target ?? 0
                 self.isf = self.provider.suggestion?.isf ?? 0
                 self.isf = self.provider.suggestion?.isf ?? 0
                 self.iob = self.provider.suggestion?.iob ?? 0
                 self.iob = self.provider.suggestion?.iob ?? 0
-                self.currentBG = (self.provider.suggestion?.bg ?? 0)
                 self.cob = self.provider.suggestion?.cob ?? 0
                 self.cob = self.provider.suggestion?.cob ?? 0
                 self.basal = self.provider.suggestion?.rate ?? 0
                 self.basal = self.provider.suggestion?.rate ?? 0
                 self.carbRatio = self.provider.suggestion?.carbRatio ?? 0
                 self.carbRatio = self.provider.suggestion?.carbRatio ?? 0
@@ -281,11 +290,8 @@ extension Bolus {
                 self.insulinRecommended = self.apsManager
                 self.insulinRecommended = self.apsManager
                     .roundBolus(amount: max(self.insulinRecommended, 0))
                     .roundBolus(amount: max(self.insulinRecommended, 0))
 
 
-                if self.useCalc {
-                    self.getCurrentBasal()
-                    self.getDeltaBG()
-                    self.insulinCalculated = self.calculateInsulin()
-                }
+                self.getCurrentBasal()
+                self.insulinCalculated = self.calculateInsulin()
             }
             }
         }
         }
 
 

+ 44 - 28
FreeAPS/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift

@@ -1,7 +1,8 @@
+import CoreData
 import SwiftUI
 import SwiftUI
 
 
 struct CurrentGlucoseView: View {
 struct CurrentGlucoseView: View {
-    @Binding var recentGlucose: BloodGlucose?
+//    @Binding var recentGlucose: BloodGlucose?
     @Binding var timerDate: Date
     @Binding var timerDate: Date
     @Binding var delta: Int?
     @Binding var delta: Int?
     @Binding var units: GlucoseUnits
     @Binding var units: GlucoseUnits
@@ -26,6 +27,13 @@ struct CurrentGlucoseView: View {
 
 
     @Environment(\.colorScheme) var colorScheme
     @Environment(\.colorScheme) var colorScheme
 
 
+    @FetchRequest(
+        entity: GlucoseStored.entity(),
+        sortDescriptors: [NSSortDescriptor(keyPath: \GlucoseStored.date, ascending: false)],
+        predicate: NSPredicate.predicateFor30MinAgo,
+        animation: Animation.bouncy
+    ) var glucoseFromPersistence: FetchedResults<GlucoseStored>
+
     private var glucoseFormatter: NumberFormatter {
     private var glucoseFormatter: NumberFormatter {
         let formatter = NumberFormatter()
         let formatter = NumberFormatter()
         formatter.numberStyle = .decimal
         formatter.numberStyle = .decimal
@@ -70,18 +78,18 @@ struct CurrentGlucoseView: View {
 
 
             VStack(alignment: .center) {
             VStack(alignment: .center) {
                 HStack {
                 HStack {
+                    let glucoseValue = glucoseFromPersistence.first?.glucose ?? 100
+                    let displayGlucose = convertGlucose(glucoseValue, to: units)
+
                     Text(
                     Text(
-                        (recentGlucose?.glucose ?? 100) == 400 ? "HIGH" : recentGlucose?.glucose
-                            .map {
-                                glucoseFormatter
-                                    .string(from: Double(units == .mmolL ? $0.asMmolL : Decimal($0)) as NSNumber)! }
-                            ?? "--"
+                        glucoseValue == 400 ? "HIGH" :
+                            glucoseFormatter.string(from: NSNumber(value: displayGlucose)) ?? "--"
                     )
                     )
                     .font(.system(size: 40, weight: .bold, design: .rounded))
                     .font(.system(size: 40, weight: .bold, design: .rounded))
                     .foregroundColor(alarm == nil ? colourGlucoseText : .loopRed)
                     .foregroundColor(alarm == nil ? colourGlucoseText : .loopRed)
                 }
                 }
                 HStack {
                 HStack {
-                    let minutesAgo = -1 * (recentGlucose?.dateString.timeIntervalSinceNow ?? 0) / 60
+                    let minutesAgo = -1 * (glucoseFromPersistence.first?.date?.timeIntervalSinceNow ?? 0) / 60
                     let text = timaAgoFormatter.string(for: Double(minutesAgo)) ?? ""
                     let text = timaAgoFormatter.string(for: Double(minutesAgo)) ?? ""
                     Text(
                     Text(
                         minutesAgo <= 1 ? "< 1 " + NSLocalizedString("min", comment: "Short form for minutes") : (
                         minutesAgo <= 1 ? "< 1 " + NSLocalizedString("min", comment: "Short form for minutes") : (
@@ -101,46 +109,54 @@ struct CurrentGlucoseView: View {
                 }.frame(alignment: .top)
                 }.frame(alignment: .top)
             }
             }
         }
         }
-        .onChange(of: recentGlucose?.direction) { newDirection in
+        .onChange(of: glucoseFromPersistence.first?.direction) { newDirection in
             withAnimation {
             withAnimation {
                 switch newDirection {
                 switch newDirection {
-                case .doubleUp,
-                     .singleUp,
-                     .tripleUp:
+                case "DoubleUp",
+                     "SingleUp",
+                     "TripleUp":
                     rotationDegrees = -90
                     rotationDegrees = -90
-
-                case .fortyFiveUp:
+                case "FortyFiveUp":
                     rotationDegrees = -45
                     rotationDegrees = -45
-
-                case .flat:
+                case "Flat":
                     rotationDegrees = 0
                     rotationDegrees = 0
-
-                case .fortyFiveDown:
+                case "FortyFiveDown":
                     rotationDegrees = 45
                     rotationDegrees = 45
-
-                case .doubleDown,
-                     .singleDown,
-                     .tripleDown:
+                case "DoubleDown",
+                     "SingleDown",
+                     "TripleDown":
                     rotationDegrees = 90
                     rotationDegrees = 90
-
-                case .none,
-                     .notComputable,
-                     .rateOutOfRange:
+                case "NONE",
+                     "NOT COMPUTABLE",
+                     "RATE OUT OF RANGE":
                     rotationDegrees = 0
                     rotationDegrees = 0
-
-                @unknown default:
+                default:
                     rotationDegrees = 0
                     rotationDegrees = 0
                 }
                 }
             }
             }
         }
         }
     }
     }
 
 
+    private func convertGlucose(_ value: Int16, to units: GlucoseUnits) -> Double {
+        switch units {
+        case .mmolL:
+            return Double(value) / 18.0
+        case .mgdL:
+            return Double(value)
+        }
+    }
+
     var colourGlucoseText: Color {
     var colourGlucoseText: Color {
-        let whichGlucose = recentGlucose?.glucose ?? 0
+        // Fetch the first glucose reading and convert it to Int for comparison
+        let whichGlucose = Int(glucoseFromPersistence.first?.glucose ?? 0)
+
+        // Define default color based on the color scheme
         let defaultColor: Color = colorScheme == .dark ? .white : .black
         let defaultColor: Color = colorScheme == .dark ? .white : .black
 
 
+        // Ensure the thresholds are logical
         guard lowGlucose < highGlucose else { return .primary }
         guard lowGlucose < highGlucose else { return .primary }
 
 
+        // Perform range checks using Int converted values
         switch whichGlucose {
         switch whichGlucose {
         case 0 ..< Int(lowGlucose):
         case 0 ..< Int(lowGlucose):
             return .loopRed
             return .loopRed

+ 1 - 0
FreeAPS/Sources/Modules/Home/View/Header/LoopView.swift

@@ -1,3 +1,4 @@
+import CoreData
 import SwiftDate
 import SwiftDate
 import SwiftUI
 import SwiftUI
 import UIKit
 import UIKit

+ 0 - 1
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -151,7 +151,6 @@ extension Home {
 
 
         var glucoseView: some View {
         var glucoseView: some View {
             CurrentGlucoseView(
             CurrentGlucoseView(
-                recentGlucose: $state.recentGlucose,
                 timerDate: $state.timerDate,
                 timerDate: $state.timerDate,
                 delta: $state.glucoseDelta,
                 delta: $state.glucoseDelta,
                 units: $state.units,
                 units: $state.units,