Forráskód Böngészése

SuggestionObserver

Ivan Valkou 5 éve
szülő
commit
a75f93ce63

+ 3 - 3
FreeAPS.xcodeproj/project.pbxproj

@@ -954,10 +954,10 @@
 		3811DE2725C9D49500A708ED /* Home */ = {
 			isa = PBXGroup;
 			children = (
-				3811DE2825C9D49500A708ED /* HomeViewModel.swift */,
-				3811DE2925C9D49500A708ED /* HomeProvider.swift */,
-				3811DE2A25C9D49500A708ED /* HomeDataFlow.swift */,
 				3811DE2B25C9D49500A708ED /* HomeBuilder.swift */,
+				3811DE2A25C9D49500A708ED /* HomeDataFlow.swift */,
+				3811DE2925C9D49500A708ED /* HomeProvider.swift */,
+				3811DE2825C9D49500A708ED /* HomeViewModel.swift */,
 				3811DE2C25C9D49500A708ED /* View */,
 			);
 			path = Home;

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

@@ -23,6 +23,7 @@ final class BaseAPSManager: APSManager, Injectable {
     @Injected() private var deviceDataManager: DeviceDataManager!
     @Injected() private var nightscout: NightscoutManager!
     @Injected() private var settingsManager: SettingsManager!
+    @Injected() private var broadcaster: Broadcaster!
     private var openAPS: OpenAPS!
 
     private var loopCancellable: AnyCancellable?
@@ -82,6 +83,14 @@ final class BaseAPSManager: APSManager, Injectable {
         .flatMap { _ in self.determineBasal() }
         .sink { _ in } receiveValue: { [weak self] ok in
             guard let self = self else { return }
+            if ok, let suggested = try? self.storage.retrieve(OpenAPS.Enact.suggested, as: Suggestion.self) {
+                DispatchQueue.main.async {
+                    self.broadcaster.notify(SuggestionObserver.self, on: .main) {
+                        $0.suggestionDidUpdate(suggested)
+                    }
+                }
+            }
+
             if ok, self.settings.closedLoop {
                 self.enactSuggested()
             }

+ 38 - 0
FreeAPS/Sources/Models/Suggestion.swift

@@ -8,4 +8,42 @@ struct Suggestion: JSON {
     let sensitivityRatio: Decimal?
     let rate: Decimal?
     let duration: Int?
+    let iob: Decimal?
+    let cob: Decimal?
+    let predictions: Predictions?
+}
+
+struct Predictions: JSON {
+    let iob: [Int]?
+    let zt: [Int]?
+    let cob: [Int]?
+    let uam: [Int]?
+}
+
+extension Suggestion {
+    private enum CodingKeys: String, CodingKey {
+        case reason
+        case units
+        case insulinReq
+        case eventualBG
+        case sensitivityRatio
+        case rate
+        case duration
+        case iob = "IOB"
+        case cob = "COB"
+        case predictions = "predBGs"
+    }
+}
+
+extension Predictions {
+    private enum CodingKeys: String, CodingKey {
+        case iob = "IOB"
+        case zt = "ZT"
+        case cob = "COB"
+        case uam = "UAM"
+    }
+}
+
+protocol SuggestionObserver {
+    func suggestionDidUpdate(_ suggestion: Suggestion)
 }

+ 10 - 1
FreeAPS/Sources/Modules/Home/HomeViewModel.swift

@@ -8,12 +8,17 @@ extension Home {
         @Injected() var temps: TempTargetsStorage!
         @Injected() var glucoseStorage: GlucoseStorage!
         @Injected() var broadcaster: Broadcaster!
+        @Injected() var storage: FileStorage!
 
         @Published var glucose: [BloodGlucose] = []
 
+        @Published var suggestion: Suggestion?
+
         override func subscribe() {
             glucose = filteredGlucose(glucoseStorage.recent())
+            suggestion = try? storage.retrieve(OpenAPS.Enact.suggested, as: Suggestion.self)
             broadcaster.register(GlucoseObserver.self, observer: self)
+            broadcaster.register(SuggestionObserver.self, observer: self)
         }
 
         func addCarbs() {
@@ -40,8 +45,12 @@ extension Home {
     }
 }
 
-extension Home.ViewModel: GlucoseObserver {
+extension Home.ViewModel: GlucoseObserver, SuggestionObserver {
     func glucoseDidUpdate(_ glucose: [BloodGlucose]) {
         self.glucose = filteredGlucose(glucose)
     }
+
+    func suggestionDidUpdate(_ suggestion: Suggestion) {
+        self.suggestion = suggestion
+    }
 }

+ 72 - 2
FreeAPS/Sources/Modules/Home/View/GlucoseChartView.swift

@@ -3,6 +3,7 @@ import SwiftUI
 
 struct GlucoseChartView: UIViewRepresentable {
     @Binding var glucose: [BloodGlucose]
+    @Binding var suggestion: Suggestion?
 
     func makeUIView(context _: Context) -> OCKCartesianGraphView {
         let view = OCKCartesianGraphView(type: .scatter)
@@ -20,10 +21,79 @@ struct GlucoseChartView: UIViewRepresentable {
         }
         var data = OCKDataSeries(
             dataPoints: dataPoints,
-            title: "Glucose",
+            title: "BG",
             color: .green
         )
         data.size = 1
-        view.dataSeries = [data]
+
+        var series = [data]
+
+        let lastDate = glucose.last?.dateString ?? Date()
+
+        if let iob = suggestion?.predictions?.iob {
+            let dataPoints = iob.enumerated().map {
+                CGPoint(
+                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
+                    y: CGFloat($1)
+                )
+            }
+            var data = OCKDataSeries(
+                dataPoints: dataPoints,
+                title: "IOB",
+                color: .blue
+            )
+            data.size = 1
+            series.append(data)
+        }
+
+        if let zt = suggestion?.predictions?.zt {
+            let dataPoints = zt.enumerated().map {
+                CGPoint(
+                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
+                    y: CGFloat($1)
+                )
+            }
+            var data = OCKDataSeries(
+                dataPoints: dataPoints,
+                title: "ZT",
+                color: .cyan
+            )
+            data.size = 1
+            series.append(data)
+        }
+
+        if let cob = suggestion?.predictions?.cob {
+            let dataPoints = cob.enumerated().map {
+                CGPoint(
+                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
+                    y: CGFloat($1)
+                )
+            }
+            var data = OCKDataSeries(
+                dataPoints: dataPoints,
+                title: "COB",
+                color: .orange
+            )
+            data.size = 1
+            series.append(data)
+        }
+
+        if let uam = suggestion?.predictions?.uam {
+            let dataPoints = uam.enumerated().map {
+                CGPoint(
+                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
+                    y: CGFloat($1)
+                )
+            }
+            var data = OCKDataSeries(
+                dataPoints: dataPoints,
+                title: "UAM",
+                color: .yellow
+            )
+            data.size = 1
+            series.append(data)
+        }
+
+        view.dataSeries = series
     }
 }

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

@@ -6,7 +6,7 @@ extension Home {
 
         var body: some View {
             Form {
-                GlucoseChartView(glucose: $viewModel.glucose).frame(height: 150)
+                GlucoseChartView(glucose: $viewModel.glucose, suggestion: $viewModel.suggestion).frame(height: 150)
                 Button(action: viewModel.addCarbs) {
                     Text("Add carbs")
                 }