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

Add Logic for infinite Overrides/ Overrides with default target

polscm32 1 год назад
Родитель
Сommit
1d11bc17a8

+ 1 - 0
FreeAPS/Sources/Modules/Home/HomeDataFlow.swift

@@ -14,4 +14,5 @@ protocol HomeProvider: Provider {
     func pumpReservoir() -> Decimal?
     func tempTarget() -> TempTarget?
     func announcement(_ hours: Int) -> [Announcement]
+    func getBGTarget() async -> BGTargets
 }

+ 6 - 0
FreeAPS/Sources/Modules/Home/HomeProvider.swift

@@ -53,5 +53,11 @@ extension Home {
             storage.retrieve(OpenAPS.Settings.pumpProfile, as: Autotune.self)?.basalProfile
                 ?? [BasalProfileEntry(start: "00:00", minutes: 0, rate: 1)]
         }
+
+        func getBGTarget() async -> BGTargets {
+            await storage.retrieveAsync(OpenAPS.Settings.bgTargets, as: BGTargets.self)
+                ?? BGTargets(from: OpenAPS.defaults(for: OpenAPS.Settings.bgTargets))
+                ?? BGTargets(units: .mgdL, userPreferredUnits: .mgdL, targets: [])
+        }
     }
 }

+ 65 - 36
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -18,13 +18,11 @@ extension Home {
         private let timer = DispatchTimer(timeInterval: 5)
         private(set) var filteredHours = 24
         @Published var manualGlucose: [BloodGlucose] = []
-        @Published var announcement: [Announcement] = []
         @Published var uploadStats = false
         @Published var recentGlucose: BloodGlucose?
         @Published var maxBasal: Decimal = 2
         @Published var autotunedBasalProfile: [BasalProfileEntry] = []
         @Published var basalProfile: [BasalProfileEntry] = []
-        @Published var tempTargets: [TempTarget] = []
         @Published var timerDate = Date()
         @Published var closedLoop = false
         @Published var pumpSuspended = false
@@ -35,7 +33,6 @@ extension Home {
         @Published var reservoir: Decimal?
         @Published var pumpName = ""
         @Published var pumpExpiresAtDate: Date?
-        @Published var tempTarget: TempTarget?
         @Published var setupPump = false
         @Published var errorMessage: String? = nil
         @Published var errorDate: Date? = nil
@@ -85,6 +82,7 @@ extension Home {
         @Published var cgmAvailable: Bool = false
         @Published var showCarbsRequiredBadge: Bool = true
         private(set) var setupPumpType: PumpConfig.PumpType = .minimed
+        @Published var currentBGTarget: Decimal = 0
 
         @Published var minForecast: [Int] = []
         @Published var maxForecast: [Int] = []
@@ -147,15 +145,9 @@ extension Home {
                         self.setupBasalProfile()
                     }
                     group.addTask {
-                        self.setupTempTargets()
-                    }
-                    group.addTask {
                         self.setupReservoir()
                     }
                     group.addTask {
-                        self.setupAnnouncements()
-                    }
-                    group.addTask {
                         self.setupCurrentPumpTimezone()
                     }
                     group.addTask {
@@ -176,6 +168,9 @@ extension Home {
                     group.addTask {
                         self.registerObservers()
                     }
+                    group.addTask {
+                        await self.getCurrentBGTarget()
+                    }
                 }
             }
         }
@@ -244,14 +239,12 @@ extension Home {
             broadcaster.register(SettingsObserver.self, observer: self)
             broadcaster.register(PumpSettingsObserver.self, observer: self)
             broadcaster.register(BasalProfileObserver.self, observer: self)
-            broadcaster.register(TempTargetsObserver.self, observer: self)
             broadcaster.register(PumpReservoirObserver.self, observer: self)
             broadcaster.register(PumpDeactivatedObserver.self, observer: self)
 
             timer.eventHandler = {
                 DispatchQueue.main.async { [weak self] in
                     self?.timerDate = Date()
-                    self?.setupCurrentTempTarget()
                 }
             }
             timer.resume()
@@ -313,6 +306,63 @@ extension Home {
                 .store(in: &lifetime)
         }
 
+        private enum SettingType {
+            case basal
+            case carbRatio
+            case bgTarget
+            case isf
+        }
+
+        private func getCurrentBGTarget() async {
+            let now = Date()
+            let calendar = Calendar.current
+            let dateFormatter = DateFormatter()
+            dateFormatter.dateFormat = "HH:mm:ss"
+            dateFormatter.timeZone = TimeZone.current
+
+            let entries: [(start: String, value: Decimal)]
+
+            let bgTargets = await provider.getBGTarget()
+            entries = bgTargets.targets.map { ($0.start, $0.low) }
+
+            for (index, entry) in entries.enumerated() {
+                guard let entryTime = dateFormatter.date(from: entry.start) else {
+                    print("Invalid entry start time: \(entry.start)")
+                    continue
+                }
+
+                let entryComponents = calendar.dateComponents([.hour, .minute, .second], from: entryTime)
+                let entryStartTime = calendar.date(
+                    bySettingHour: entryComponents.hour!,
+                    minute: entryComponents.minute!,
+                    second: entryComponents.second!,
+                    of: now
+                )!
+
+                let entryEndTime: Date
+                if index < entries.count - 1,
+                   let nextEntryTime = dateFormatter.date(from: entries[index + 1].start)
+                {
+                    let nextEntryComponents = calendar.dateComponents([.hour, .minute, .second], from: nextEntryTime)
+                    entryEndTime = calendar.date(
+                        bySettingHour: nextEntryComponents.hour!,
+                        minute: nextEntryComponents.minute!,
+                        second: nextEntryComponents.second!,
+                        of: now
+                    )!
+                } else {
+                    entryEndTime = calendar.date(byAdding: .day, value: 1, to: entryStartTime)!
+                }
+
+                if now >= entryStartTime, now < entryEndTime {
+                    await MainActor.run {
+                        currentBGTarget = entry.value
+                    }
+                    return
+                }
+            }
+        }
+
         @MainActor private func setupSettings() async {
             units = settingsManager.settings.units
             allowManualTemp = !settingsManager.settings.closedLoop
@@ -320,7 +370,6 @@ extension Home {
             lastLoopDate = apsManager.lastLoopDate
             alarm = provider.glucoseStorage.alarm
             manualTempBasal = apsManager.isManualTempBasal
-            setupCurrentTempTarget()
             isSmoothingEnabled = settingsManager.settings.smoothGlucose
             maxValue = settingsManager.preferences.autosensMax
             lowGlucose = units == .mgdL ? settingsManager.settings.low : settingsManager.settings.low.asMmolL
@@ -473,21 +522,6 @@ extension Home {
             }
         }
 
-        private func setupTempTargets() {
-            DispatchQueue.main.async { [weak self] in
-                guard let self = self else { return }
-                self.manualTempBasal = self.apsManager.isManualTempBasal
-                self.tempTargets = self.provider.tempTargets(hours: self.filteredHours)
-            }
-        }
-
-        private func setupAnnouncements() {
-            DispatchQueue.main.async { [weak self] in
-                guard let self = self else { return }
-                self.announcement = self.provider.announcement(self.filteredHours)
-            }
-        }
-
         private func setupReservoir() {
             DispatchQueue.main.async { [weak self] in
                 guard let self = self else { return }
@@ -495,10 +529,6 @@ extension Home {
             }
         }
 
-        private func setupCurrentTempTarget() {
-            tempTarget = provider.tempTarget()
-        }
-
         private func setupCurrentPumpTimezone() {
             DispatchQueue.main.async { [weak self] in
                 guard let self = self else { return }
@@ -518,7 +548,6 @@ extension Home.StateModel:
     SettingsObserver,
     PumpSettingsObserver,
     BasalProfileObserver,
-    TempTargetsObserver,
     PumpReservoirObserver,
     PumpTimeZoneObserver,
     PumpDeactivatedObserver
@@ -550,6 +579,10 @@ extension Home.StateModel:
         cgmAvailable = (fetchGlucoseManager.cgmGlucoseSourceType != CGMType.none)
         displayPumpStatusHighlightMessage()
         setupBatteryArray()
+
+        Task {
+            await self.getCurrentBGTarget()
+        }
     }
 
     // TODO: is this ever really triggered? react to MOC changes?
@@ -566,10 +599,6 @@ extension Home.StateModel:
         setupBasalProfile()
     }
 
-    func tempTargetsDidUpdate(_: [TempTarget]) {
-        setupTempTargets()
-    }
-
     func pumpReservoirDidChange(_: Decimal) {
         setupReservoir()
         displayPumpStatusHighlightMessage()

+ 0 - 6
FreeAPS/Sources/Modules/Home/View/Chart/BasalChart.swift

@@ -32,12 +32,6 @@ extension MainChartView {
             .onChange(of: state.maxBasal) { _ in
                 calculateBasals()
             }
-            .onChange(of: state.autotunedBasalProfile) { _ in
-                calculateBasals()
-            }
-            .onChange(of: state.basalProfile) { _ in
-                calculateBasals()
-            }
             .frame(minHeight: geo.size.height * 0.05)
             .frame(width: fullWidth(viewWidth: screenSize.width))
             .chartXScale(domain: startMarker ... endMarker)

+ 1 - 2
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -9,7 +9,6 @@ struct MainChartView: View {
     var geo: GeometryProxy
     @Binding var units: GlucoseUnits
     @Binding var hours: Int
-    @Binding var tempTargets: [TempTarget]
     @Binding var highGlucose: Decimal
     @Binding var lowGlucose: Decimal
     @Binding var screenHours: Int16
@@ -21,7 +20,6 @@ struct MainChartView: View {
 
     @State var basalProfiles: [BasalProfile] = []
     @State var preparedTempBasals: [(start: Date, end: Date, rate: Double)] = []
-//    @State var chartTempTargets: [ChartTempTarget] = []
     @State var startMarker =
         Date(timeIntervalSinceNow: TimeInterval(hours: -24))
     @State var endMarker = Date(timeIntervalSinceNow: TimeInterval(hours: 3))
@@ -169,6 +167,7 @@ extension MainChartView {
                 )
 
                 OverrideView(
+                    state: state,
                     overrides: state.overrides,
                     overrideRunStored: state.overrideRunStored,
                     units: state.units,

+ 28 - 18
FreeAPS/Sources/Modules/Home/View/Chart/OverrideView.swift

@@ -4,6 +4,7 @@ import Foundation
 import SwiftUI
 
 struct OverrideView: ChartContent {
+    @ObservedObject var state: Home.StateModel // @ObservedObject will be replaced when converting to Observable
     let overrides: [OverrideStored]
     let overrideRunStored: [OverrideRunStored]
     let units: GlucoseUnits
@@ -16,28 +17,24 @@ struct OverrideView: ChartContent {
 
     private func drawActiveOverrides() -> some ChartContent {
         ForEach(overrides) { override in
-            if let duration = MainChartHelper.calculateDuration(
+            let start: Date = override.date ?? .distantPast
+            let duration = MainChartHelper.calculateDuration(
                 objectID: override.objectID,
                 attribute: "duration",
                 context: viewContext
-            ) {
-                let start: Date = override.date ?? .distantPast
-                let end: Date = start.addingTimeInterval(duration)
+            ) ?? 0
+            let end: Date = duration != 0 ? start.addingTimeInterval(duration) : start
+                .addingTimeInterval(6 * 60 * 60) // handle infinite overrides
 
-                if let target = MainChartHelper.calculateTarget(
-                    objectID: override.objectID,
-                    attribute: "target",
-                    context: viewContext
-                ) {
-                    RuleMark(
-                        xStart: .value("Start", start, unit: .second),
-                        xEnd: .value("End", end, unit: .second),
-                        y: .value("Value", units == .mgdL ? target : target.asMmolL)
-                    )
-                    .foregroundStyle(Color.purple.opacity(0.4))
-                    .lineStyle(.init(lineWidth: 8))
-                }
-            }
+            let target = getOverrideTarget(override: override)
+
+            RuleMark(
+                xStart: .value("Start", start, unit: .second),
+                xEnd: .value("End", end, unit: .second),
+                y: .value("Value", units == .mgdL ? target : target.asMmolL)
+            )
+            .foregroundStyle(Color.purple.opacity(0.4))
+            .lineStyle(.init(lineWidth: 8))
         }
     }
 
@@ -55,4 +52,17 @@ struct OverrideView: ChartContent {
             .lineStyle(.init(lineWidth: 8))
         }
     }
+
+    // Handle Overrides where no Target is provided
+    private func getOverrideTarget(override: OverrideStored) -> Decimal {
+        if let target = MainChartHelper
+            .calculateTarget(objectID: override.objectID, attribute: "target", context: viewContext)
+        {
+            return target
+        } else if override.target == 0 {
+            return state.currentBGTarget // Default target
+        } else {
+            return override.target?.decimalValue ?? state.currentBGTarget
+        }
+    }
 }

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

@@ -352,7 +352,6 @@ extension Home {
                     geo: geo,
                     units: $state.units,
                     hours: .constant(state.filteredHours),
-                    tempTargets: $state.tempTargets,
                     highGlucose: $state.highGlucose,
                     lowGlucose: $state.lowGlucose,
                     screenHours: $state.hours,