Ivan Valkou 5 лет назад
Родитель
Сommit
a37399c268

+ 34 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -83,6 +83,10 @@
 		383948DA25CD64D500E91849 /* Glucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 383948D925CD64D500E91849 /* Glucose.swift */; };
 		383948DA25CD64D500E91849 /* Glucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 383948D925CD64D500E91849 /* Glucose.swift */; };
 		384E803425C385E60086DB71 /* JavaScriptWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E803325C385E60086DB71 /* JavaScriptWorker.swift */; };
 		384E803425C385E60086DB71 /* JavaScriptWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E803325C385E60086DB71 /* JavaScriptWorker.swift */; };
 		384E803825C388640086DB71 /* Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E803725C388640086DB71 /* Script.swift */; };
 		384E803825C388640086DB71 /* Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = 384E803725C388640086DB71 /* Script.swift */; };
+		386ED25E25EE48B500820A49 /* MockKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38B17ADB25DD6A40005CAE3D /* MockKit.framework */; };
+		386ED25F25EE48B500820A49 /* MockKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 38B17ADB25DD6A40005CAE3D /* MockKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		386ED26025EE48B500820A49 /* MockKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38B17ADF25DD6A40005CAE3D /* MockKitUI.framework */; };
+		386ED26125EE48B500820A49 /* MockKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 38B17ADF25DD6A40005CAE3D /* MockKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		3870FF4725EC187A0088248F /* BloodGlucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3870FF4225EC13F40088248F /* BloodGlucose.swift */; };
 		3870FF4725EC187A0088248F /* BloodGlucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3870FF4225EC13F40088248F /* BloodGlucose.swift */; };
 		3871F38725ED661C0013ECB5 /* Suggestion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3871F38625ED661C0013ECB5 /* Suggestion.swift */; };
 		3871F38725ED661C0013ECB5 /* Suggestion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3871F38625ED661C0013ECB5 /* Suggestion.swift */; };
 		3871F39C25ED892B0013ECB5 /* TempTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3871F39B25ED892B0013ECB5 /* TempTarget.swift */; };
 		3871F39C25ED892B0013ECB5 /* TempTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3871F39B25ED892B0013ECB5 /* TempTarget.swift */; };
@@ -164,6 +168,20 @@
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
 /* Begin PBXContainerItemProxy section */
 /* Begin PBXContainerItemProxy section */
+		386ED26C25EE48D600820A49 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 38B17AC025DD6A40005CAE3D /* LoopKit.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = 89D2047121CC7BD7001238CC;
+			remoteInfo = MockKit;
+		};
+		386ED26E25EE48D600820A49 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 38B17AC025DD6A40005CAE3D /* LoopKit.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = 89D2048E21CC7C12001238CC;
+			remoteInfo = MockKitUI;
+		};
 		38B17AB525DD69FA005CAE3D /* PBXContainerItemProxy */ = {
 		38B17AB525DD69FA005CAE3D /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			isa = PBXContainerItemProxy;
 			containerPortal = 38B17AAE25DD69FA005CAE3D /* SwiftCharts.xcodeproj */;
 			containerPortal = 38B17AAE25DD69FA005CAE3D /* SwiftCharts.xcodeproj */;
@@ -505,11 +523,13 @@
 				38B17B9725DD941A005CAE3D /* RileyLinkKit.framework in Embed Frameworks */,
 				38B17B9725DD941A005CAE3D /* RileyLinkKit.framework in Embed Frameworks */,
 				38B17B9925DD941A005CAE3D /* RileyLinkKitUI.framework in Embed Frameworks */,
 				38B17B9925DD941A005CAE3D /* RileyLinkKitUI.framework in Embed Frameworks */,
 				38B17B8725DD93BA005CAE3D /* LoopKit.framework in Embed Frameworks */,
 				38B17B8725DD93BA005CAE3D /* LoopKit.framework in Embed Frameworks */,
+				386ED25F25EE48B500820A49 /* MockKit.framework in Embed Frameworks */,
 				38B17B9125DD9419005CAE3D /* MinimedKit.framework in Embed Frameworks */,
 				38B17B9125DD9419005CAE3D /* MinimedKit.framework in Embed Frameworks */,
 				38A504A625DD9FDA00C5B9E8 /* OmniKit.framework in Embed Frameworks */,
 				38A504A625DD9FDA00C5B9E8 /* OmniKit.framework in Embed Frameworks */,
 				38B17BEE25DD987B005CAE3D /* NightscoutUploadKit.framework in Embed Frameworks */,
 				38B17BEE25DD987B005CAE3D /* NightscoutUploadKit.framework in Embed Frameworks */,
 				38B17B8F25DD9419005CAE3D /* Crypto.framework in Embed Frameworks */,
 				38B17B8F25DD9419005CAE3D /* Crypto.framework in Embed Frameworks */,
 				38B17B9525DD941A005CAE3D /* RileyLinkBLEKit.framework in Embed Frameworks */,
 				38B17B9525DD941A005CAE3D /* RileyLinkBLEKit.framework in Embed Frameworks */,
+				386ED26125EE48B500820A49 /* MockKitUI.framework in Embed Frameworks */,
 				38B17B8B25DD93F1005CAE3D /* MKRingProgressView.framework in Embed Frameworks */,
 				38B17B8B25DD93F1005CAE3D /* MKRingProgressView.framework in Embed Frameworks */,
 				38B17B8925DD93BA005CAE3D /* LoopKitUI.framework in Embed Frameworks */,
 				38B17B8925DD93BA005CAE3D /* LoopKitUI.framework in Embed Frameworks */,
 				38A504A825DD9FDA00C5B9E8 /* OmniKitUI.framework in Embed Frameworks */,
 				38A504A825DD9FDA00C5B9E8 /* OmniKitUI.framework in Embed Frameworks */,
@@ -666,11 +686,13 @@
 				38B17BED25DD987B005CAE3D /* NightscoutUploadKit.framework in Frameworks */,
 				38B17BED25DD987B005CAE3D /* NightscoutUploadKit.framework in Frameworks */,
 				38B17B8C25DD9404005CAE3D /* SwiftCharts.framework in Frameworks */,
 				38B17B8C25DD9404005CAE3D /* SwiftCharts.framework in Frameworks */,
 				38B17B9825DD941A005CAE3D /* RileyLinkKitUI.framework in Frameworks */,
 				38B17B9825DD941A005CAE3D /* RileyLinkKitUI.framework in Frameworks */,
+				386ED25E25EE48B500820A49 /* MockKit.framework in Frameworks */,
 				3811DE1025C9D37700A708ED /* Swinject in Frameworks */,
 				3811DE1025C9D37700A708ED /* Swinject in Frameworks */,
 				383948D325CD4D6D00E91849 /* Disk in Frameworks */,
 				383948D325CD4D6D00E91849 /* Disk in Frameworks */,
 				38B17B9425DD941A005CAE3D /* RileyLinkBLEKit.framework in Frameworks */,
 				38B17B9425DD941A005CAE3D /* RileyLinkBLEKit.framework in Frameworks */,
 				38B17B8825DD93BA005CAE3D /* LoopKitUI.framework in Frameworks */,
 				38B17B8825DD93BA005CAE3D /* LoopKitUI.framework in Frameworks */,
 				38A504A525DD9FDA00C5B9E8 /* OmniKit.framework in Frameworks */,
 				38A504A525DD9FDA00C5B9E8 /* OmniKit.framework in Frameworks */,
+				386ED26025EE48B500820A49 /* MockKitUI.framework in Frameworks */,
 				38A504A725DD9FDA00C5B9E8 /* OmniKitUI.framework in Frameworks */,
 				38A504A725DD9FDA00C5B9E8 /* OmniKitUI.framework in Frameworks */,
 				38B17B9025DD9419005CAE3D /* MinimedKit.framework in Frameworks */,
 				38B17B9025DD9419005CAE3D /* MinimedKit.framework in Frameworks */,
 				38B17B6625DD90E0005CAE3D /* SwiftDate in Frameworks */,
 				38B17B6625DD90E0005CAE3D /* SwiftDate in Frameworks */,
@@ -1299,6 +1321,8 @@
 			buildRules = (
 			buildRules = (
 			);
 			);
 			dependencies = (
 			dependencies = (
+				386ED26D25EE48D600820A49 /* PBXTargetDependency */,
+				386ED26F25EE48D600820A49 /* PBXTargetDependency */,
 				38B17B4025DD6BE0005CAE3D /* PBXTargetDependency */,
 				38B17B4025DD6BE0005CAE3D /* PBXTargetDependency */,
 				38B17B4225DD6BE0005CAE3D /* PBXTargetDependency */,
 				38B17B4225DD6BE0005CAE3D /* PBXTargetDependency */,
 				38B17B4425DD6BE0005CAE3D /* PBXTargetDependency */,
 				38B17B4425DD6BE0005CAE3D /* PBXTargetDependency */,
@@ -1804,6 +1828,16 @@
 /* End PBXSourcesBuildPhase section */
 /* End PBXSourcesBuildPhase section */
 
 
 /* Begin PBXTargetDependency section */
 /* Begin PBXTargetDependency section */
+		386ED26D25EE48D600820A49 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MockKit;
+			targetProxy = 386ED26C25EE48D600820A49 /* PBXContainerItemProxy */;
+		};
+		386ED26F25EE48D600820A49 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MockKitUI;
+			targetProxy = 386ED26E25EE48D600820A49 /* PBXContainerItemProxy */;
+		};
 		38B17ABF25DD6A0A005CAE3D /* PBXTargetDependency */ = {
 		38B17ABF25DD6A0A005CAE3D /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			isa = PBXTargetDependency;
 			name = SwiftCharts;
 			name = SwiftCharts;

+ 1 - 0
FreeAPS/Resources/json/defaults/monitor/glucose.json

@@ -0,0 +1 @@
+[]

+ 1 - 0
FreeAPS/Resources/json/defaults/monitor/pumphistory-24h-zoned.json

@@ -0,0 +1 @@
+[]

+ 1 - 15
FreeAPS/Resources/json/defaults/settings/temptargets.json

@@ -1,15 +1 @@
-[
-    {
-        "_id": "601bf716211b34b896be0e24",
-        "eventType": "Temporary Target",
-        "entededBy": "Automagic",
-        "reason": "Manual",
-        "targetTop": 126,
-        "targetBottom": 126,
-        "duration": 300,
-        "created_at": "2021-02-04T13:31:02.076Z",
-        "utcOffset": 0,
-        "carbs": null,
-        "insulin": null
-    }
-]
+[]

+ 11 - 15
FreeAPS/Sources/APS/APSManager.swift

@@ -6,8 +6,6 @@ import Swinject
 
 
 protocol APSManager {
 protocol APSManager {
     func determineBasal()
     func determineBasal()
-    func runTest()
-    func makeProfiles()
     func fetchLastGlucose()
     func fetchLastGlucose()
     func autosense()
     func autosense()
     func autotune()
     func autotune()
@@ -45,24 +43,22 @@ final class BaseAPSManager: APSManager, Injectable {
     func loop() {}
     func loop() {}
 
 
     func determineBasal() {
     func determineBasal() {
+        guard let glucose = try? storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self), glucose.count >= 36 else {
+            print("Not enough glucose data")
+            return
+        }
+
         let now = Date()
         let now = Date()
         guard let temp = currentTemp(date: now) else { return }
         guard let temp = currentTemp(date: now) else { return }
-        determineBasalCancellable = openAPS
-            .determineBasal(currentTemp: temp, clock: now)
+        determineBasalCancellable = openAPS.makeProfiles()
+            .flatMap { _ in
+                self.openAPS.determineBasal(currentTemp: temp, clock: now)
+            }
             .sink { [weak self] in
             .sink { [weak self] in
                 self?.enactSuggested()
                 self?.enactSuggested()
             }
             }
     }
     }
 
 
-    func runTest() {
-        openAPS.test()
-    }
-
-    func makeProfiles() {
-        openAPS.makeProfile(autotuned: false)
-        openAPS.makeProfile(autotuned: true)
-    }
-
     func fetchLastGlucose() {
     func fetchLastGlucose() {
         if let urlString = keychain.getValue(String.self, forKey: NightscoutConfig.Config.urlKey),
         if let urlString = keychain.getValue(String.self, forKey: NightscoutConfig.Config.urlKey),
            let url = URL(string: urlString)
            let url = URL(string: urlString)
@@ -76,11 +72,11 @@ final class BaseAPSManager: APSManager, Injectable {
     }
     }
 
 
     func autosense() {
     func autosense() {
-        openAPS.autosense()
+        _ = openAPS.autosense()
     }
     }
 
 
     func autotune() {
     func autotune() {
-        openAPS.autotune()
+        _ = openAPS.autotune()
     }
     }
 
 
     private func currentTemp(date: Date) -> TempBasal? {
     private func currentTemp(date: Date) -> TempBasal? {

+ 3 - 1
FreeAPS/Sources/APS/DeviceDataManager.swift

@@ -3,6 +3,7 @@ import Foundation
 import LoopKit
 import LoopKit
 import LoopKitUI
 import LoopKitUI
 import MinimedKit
 import MinimedKit
+import MockKit
 import OmniKit
 import OmniKit
 import SwiftDate
 import SwiftDate
 import Swinject
 import Swinject
@@ -15,7 +16,8 @@ protocol DeviceDataManager {
 
 
 private let staticPumpManagers: [PumpManagerUI.Type] = [
 private let staticPumpManagers: [PumpManagerUI.Type] = [
     MinimedPumpManager.self,
     MinimedPumpManager.self,
-    OmnipodPumpManager.self
+    OmnipodPumpManager.self,
+    MockPumpManager.self
 ]
 ]
 
 
 private let staticPumpManagersByIdentifier: [String: PumpManagerUI.Type] = staticPumpManagers.reduce(into: [:]) { map, Type in
 private let staticPumpManagersByIdentifier: [String: PumpManagerUI.Type] = staticPumpManagers.reduce(into: [:]) { map, Type in

+ 87 - 160
FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift

@@ -73,180 +73,107 @@ final class OpenAPS {
         }.eraseToAnyPublisher()
         }.eraseToAnyPublisher()
     }
     }
 
 
-    func autosense() {
-        processQueue.async {
-            let pumpHistory = self.loadFileFromStorage(name: OpenAPS.Monitor.pumpHistory)
-            let carbs = self.loadFileFromStorage(name: Monitor.carbHistory)
-            let glucose = self.loadFileFromStorage(name: Monitor.glucose)
-            let profile = self.loadFileFromStorage(name: Settings.profile)
-            let basalProfile = self.loadFileFromStorage(name: Settings.basalProfile)
-
-            let autosensResult = self.autosense(
-                pumpHistory: pumpHistory,
-                profile: profile,
-                carbs: carbs,
-                glucose: glucose,
-                basalprofile: basalProfile,
-                temptargets: RawJSON.null
-            )
+    func autosense() -> AnyPublisher<Void, Never> {
+        Future { promise in
+            self.processQueue.async {
+                let pumpHistory = self.loadFileFromStorage(name: OpenAPS.Monitor.pumpHistory)
+                let carbs = self.loadFileFromStorage(name: Monitor.carbHistory)
+                let glucose = self.loadFileFromStorage(name: Monitor.glucose)
+                let profile = self.loadFileFromStorage(name: Settings.profile)
+                let basalProfile = self.loadFileFromStorage(name: Settings.basalProfile)
 
 
-            print("AUTOSENS: \(autosensResult)")
-            try? self.storage.save(autosensResult, as: Settings.autosense)
-        }
-    }
+                let autosensResult = self.autosense(
+                    pumpHistory: pumpHistory,
+                    profile: profile,
+                    carbs: carbs,
+                    glucose: glucose,
+                    basalprofile: basalProfile,
+                    temptargets: RawJSON.null
+                )
 
 
-    func autotune(categorizeUamAsBasal: Bool = false, tuneInsulinCurve: Bool = false) {
-        processQueue.async {
-            let pumpHistory = self.loadFileFromStorage(name: OpenAPS.Monitor.pumpHistory)
-            let glucose = self.loadFileFromStorage(name: Monitor.glucose)
-            let profile = self.loadFileFromStorage(name: Settings.profile)
-
-            let autotunePreppedGlucose = self.autotunePrepare(
-                pumphistory: pumpHistory,
-                profile: profile,
-                glucose: glucose,
-                pumpprofile: profile,
-                categorizeUamAsBasal: categorizeUamAsBasal,
-                tuneInsulinCurve: tuneInsulinCurve
-            )
-            print("AUTOTUNE PREP: \(autotunePreppedGlucose)")
+                print("AUTOSENS: \(autosensResult)")
+                try? self.storage.save(autosensResult, as: Settings.autosense)
+                promise(.success(()))
+            }
+        }.eraseToAnyPublisher()
+    }
 
 
-            let previousAutotune = try? self.storage.retrieve(Settings.autotune, as: RawJSON.self)
+    func autotune(categorizeUamAsBasal: Bool = false, tuneInsulinCurve: Bool = false) -> AnyPublisher<Void, Never> {
+        Future { promise in
+            self.processQueue.async {
+                let pumpHistory = self.loadFileFromStorage(name: OpenAPS.Monitor.pumpHistory)
+                let glucose = self.loadFileFromStorage(name: Monitor.glucose)
+                let profile = self.loadFileFromStorage(name: Settings.profile)
 
 
-            let autotuneResult = self.autotuneRun(
-                autotunePreparedData: autotunePreppedGlucose,
-                previousAutotuneResult: previousAutotune ?? profile,
-                pumpProfile: profile
-            )
+                let autotunePreppedGlucose = self.autotunePrepare(
+                    pumphistory: pumpHistory,
+                    profile: profile,
+                    glucose: glucose,
+                    pumpprofile: profile,
+                    categorizeUamAsBasal: categorizeUamAsBasal,
+                    tuneInsulinCurve: tuneInsulinCurve
+                )
+                print("AUTOTUNE PREP: \(autotunePreppedGlucose)")
 
 
-            try? self.storage.save(autotuneResult, as: Settings.autotune)
+                let previousAutotune = try? self.storage.retrieve(Settings.autotune, as: RawJSON.self)
 
 
-            print("AUTOTUNE RESULT: \(autotuneResult)")
-        }
-    }
-
-    func makeProfile(autotuned: Bool) {
-        processQueue.async {
-            print("MAKE PROFILE autotuned \(autotuned)")
-            let preferences = self.loadFileFromStorage(name: Settings.preferences)
-            let pumpSettings = self.loadFileFromStorage(name: Settings.settings)
-            let bgTargets = self.loadFileFromStorage(name: Settings.bgTargets)
-            let basalProfile = self.loadFileFromStorage(name: Settings.basalProfile)
-            let isf = self.loadFileFromStorage(name: Settings.insulinSensitivities)
-            let cr = self.loadFileFromStorage(name: Settings.carbRatios)
-            let tempTargets = self.loadFileFromStorage(name: Settings.tempTargets)
-            let model = self.loadFileFromStorage(name: Settings.model)
-            let autotune = self.loadFileFromStorage(name: Settings.autotune)
-
-            let aututune = autotuned ? (autotune.isEmpty ? .null : autotune) : .null
-
-            let profile = self.makeProfile(
-                preferences: preferences,
-                pumpSettings: pumpSettings,
-                bgTargets: bgTargets,
-                basalProfile: basalProfile,
-                isf: isf,
-                carbRatio: cr,
-                tempTargets: tempTargets,
-                model: model,
-                autotune: aututune
-            )
+                let autotuneResult = self.autotuneRun(
+                    autotunePreparedData: autotunePreppedGlucose,
+                    previousAutotuneResult: previousAutotune ?? profile,
+                    pumpProfile: profile
+                )
 
 
-            print("PROFILE RESULT \n\(profile)")
+                try? self.storage.save(autotuneResult, as: Settings.autotune)
 
 
-            if autotuned {
-                try? self.storage.save(profile, as: Settings.profile)
-            } else {
-                try? self.storage.save(profile, as: Settings.pumpProfile)
+                print("AUTOTUNE RESULT: \(autotuneResult)")
+                promise(.success(()))
             }
             }
-        }
+        }.eraseToAnyPublisher()
     }
     }
 
 
-    func test() {
-        processQueue.async {
-            let now = Date()
-            print("START at \(now)")
-            let pumphistory = self.loadJSON(name: "pumphistory")
-            let profile = self.loadJSON(name: "profile")
-            let basalProfile = self.loadJSON(name: "basal_profile")
-            let clock = self.loadJSON(name: "clock")
-            let carbs = self.loadJSON(name: "carbhistory")
-            let glucose = self.loadJSON(name: "glucose")
-            let currentTemp = self.loadJSON(name: "temp_basal")
-            let reservoir = 100
-
-            let preferences = self.exportDefaultPreferences()
-
-            print("DEFAULT PREFERENCES: \(preferences)")
-
-            let autosensResult = self.autosense(
-                pumpHistory: pumphistory,
-                profile: profile,
-                carbs: carbs,
-                glucose: glucose,
-                basalprofile: basalProfile,
-                temptargets: RawJSON.null
-            )
-            print("AUTOSENS: \(autosensResult)")
-            try? self.storage.save(autosensResult, as: Settings.autosense)
-
-            let iobResult = self.iob(
-                pumphistory: pumphistory,
-                profile: profile,
-                clock: clock,
-                autosens: autosensResult
-            )
-            print("IOB: \(iobResult)")
-
-            let mealResult = self.meal(
-                pumphistory: pumphistory,
-                profile: profile,
-                basalProfile: basalProfile,
-                clock: clock,
-                carbs: carbs,
-                glucose: glucose
-            )
-
-            print("MEAL: \(mealResult)")
-            try? self.storage.save(mealResult, as: Monitor.meal)
-
-            let suggested = self.determineBasal(
-                glucose: glucose,
-                currentTemp: currentTemp,
-                iob: iobResult,
-                profile: profile,
-                autosens: autosensResult,
-                meal: mealResult,
-                microBolusAllowed: true,
-                reservoir: reservoir
-            )
-            print("SUGGESTED: \(suggested)")
-
-            let autotunePreppedGlucose = self.autotunePrepare(
-                pumphistory: pumphistory,
-                profile: profile,
-                glucose: glucose,
-                pumpprofile: profile,
-                categorizeUamAsBasal: true,
-                tuneInsulinCurve: false
-            )
-            print("AUTOTUNE PREP: \(autotunePreppedGlucose)")
-
-            let previousAutotune = try? self.storage.retrieve(Settings.autotune, as: RawJSON.self)
-
-            let autotuneResult = self.autotuneRun(
-                autotunePreparedData: autotunePreppedGlucose,
-                previousAutotuneResult: previousAutotune ?? profile,
-                pumpProfile: profile
-            )
+    func makeProfiles() -> AnyPublisher<Void, Never> {
+        Future { promise in
+            self.processQueue.async {
+                let preferences = self.loadFileFromStorage(name: Settings.preferences)
+                let pumpSettings = self.loadFileFromStorage(name: Settings.settings)
+                let bgTargets = self.loadFileFromStorage(name: Settings.bgTargets)
+                let basalProfile = self.loadFileFromStorage(name: Settings.basalProfile)
+                let isf = self.loadFileFromStorage(name: Settings.insulinSensitivities)
+                let cr = self.loadFileFromStorage(name: Settings.carbRatios)
+                let tempTargets = self.loadFileFromStorage(name: Settings.tempTargets)
+                let model = self.loadFileFromStorage(name: Settings.model)
+                let autotune = self.loadFileFromStorage(name: Settings.autotune)
+
+                let pumpProfile = self.makeProfile(
+                    preferences: preferences,
+                    pumpSettings: pumpSettings,
+                    bgTargets: bgTargets,
+                    basalProfile: basalProfile,
+                    isf: isf,
+                    carbRatio: cr,
+                    tempTargets: tempTargets,
+                    model: model,
+                    autotune: RawJSON.null
+                )
 
 
-            try? self.storage.save(autotuneResult, as: Settings.autotune)
+                let profile = self.makeProfile(
+                    preferences: preferences,
+                    pumpSettings: pumpSettings,
+                    bgTargets: bgTargets,
+                    basalProfile: basalProfile,
+                    isf: isf,
+                    carbRatio: cr,
+                    tempTargets: tempTargets,
+                    model: model,
+                    autotune: autotune.isEmpty ? .null : autotune
+                )
 
 
-            print("AUTOTUNE RESULT: \(autotuneResult)")
+                try? self.storage.save(pumpProfile, as: Settings.pumpProfile)
+                try? self.storage.save(profile, as: Settings.profile)
 
 
-            let finishDate = Date()
-            print("FINISH at \(finishDate), duration \(finishDate.timeIntervalSince(now)) s")
-        }
+                promise(.success(()))
+            }
+        }.eraseToAnyPublisher()
     }
     }
 
 
     // MARK: - Private
     // MARK: - Private

+ 23 - 8
FreeAPS/Sources/Modules/Home/HomeViewModel.swift

@@ -4,14 +4,7 @@ extension Home {
     class ViewModel<Provider>: BaseViewModel<Provider>, ObservableObject where Provider: HomeProvider {
     class ViewModel<Provider>: BaseViewModel<Provider>, ObservableObject where Provider: HomeProvider {
         @Injected() var apsManager: APSManager!
         @Injected() var apsManager: APSManager!
         @Injected() var history: PumpHistoryStorage!
         @Injected() var history: PumpHistoryStorage!
-
-        func runOpenAPS() {
-            apsManager.runTest()
-        }
-
-        func makeProfiles() {
-            apsManager.makeProfiles()
-        }
+        @Injected() var temps: TempTargetsStorage!
 
 
         func fetchGlucose() {
         func fetchGlucose() {
             apsManager.fetchLastGlucose()
             apsManager.fetchLastGlucose()
@@ -24,5 +17,27 @@ extension Home {
         func runLoop() {
         func runLoop() {
             apsManager.determineBasal()
             apsManager.determineBasal()
         }
         }
+
+        func addHighTempTarget() {
+            temps
+                .storeTempTargets([TempTarget(
+                    id: UUID().uuidString,
+                    createdAt: Date(),
+                    targetTop: 126,
+                    targetBottom: 126,
+                    duration: 10
+                )])
+        }
+
+        func addLowTempTarget() {
+            temps
+                .storeTempTargets([TempTarget(
+                    id: UUID().uuidString,
+                    createdAt: Date(),
+                    targetTop: 81,
+                    targetBottom: 81,
+                    duration: 10
+                )])
+        }
     }
     }
 }
 }

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

@@ -7,26 +7,26 @@ extension Home {
         var body: some View {
         var body: some View {
             VStack {
             VStack {
                 Spacer()
                 Spacer()
-                Button(action: viewModel.runOpenAPS) {
-                    Text("Run test")
+                Button(action: viewModel.fetchGlucose) {
+                    Text("Fetch glucose")
                         .frame(maxWidth: .infinity)
                         .frame(maxWidth: .infinity)
                         .foregroundColor(.white)
                         .foregroundColor(.white)
                         .buttonBackground()
                         .buttonBackground()
                 }
                 }
-                Button(action: viewModel.makeProfiles) {
-                    Text("Make profiles")
+                Button(action: viewModel.addCarbs) {
+                    Text("Add 15 g carbs")
                         .frame(maxWidth: .infinity)
                         .frame(maxWidth: .infinity)
                         .foregroundColor(.white)
                         .foregroundColor(.white)
                         .buttonBackground()
                         .buttonBackground()
                 }
                 }
-                Button(action: viewModel.fetchGlucose) {
-                    Text("Fetch glucose")
+                Button(action: viewModel.addHighTempTarget) {
+                    Text("Temp target 7.0 mmol/L for 10 min")
                         .frame(maxWidth: .infinity)
                         .frame(maxWidth: .infinity)
                         .foregroundColor(.white)
                         .foregroundColor(.white)
                         .buttonBackground()
                         .buttonBackground()
                 }
                 }
-                Button(action: viewModel.addCarbs) {
-                    Text("Add 15 g carbs")
+                Button(action: viewModel.addLowTempTarget) {
+                    Text("Temp target 4.5 mmol/L for 10 min")
                         .frame(maxWidth: .infinity)
                         .frame(maxWidth: .infinity)
                         .foregroundColor(.white)
                         .foregroundColor(.white)
                         .buttonBackground()
                         .buttonBackground()

+ 1 - 0
FreeAPS/Sources/Modules/PumpConfig/PumpConfigDataFlow.swift

@@ -8,6 +8,7 @@ enum PumpConfig {
     enum PumpType: Equatable {
     enum PumpType: Equatable {
         case minimed
         case minimed
         case omnipod
         case omnipod
+        case simulator
     }
     }
 
 
     struct PumpInitialSettings {
     struct PumpInitialSettings {

+ 1 - 0
FreeAPS/Sources/Modules/PumpConfig/View/PumpConfigRootView.swift

@@ -19,6 +19,7 @@ extension PumpConfig {
                     } else {
                     } else {
                         Button("Add Medtronic") { viewModel.addPump(.minimed) }
                         Button("Add Medtronic") { viewModel.addPump(.minimed) }
                         Button("Add Omnipod") { viewModel.addPump(.omnipod) }
                         Button("Add Omnipod") { viewModel.addPump(.omnipod) }
+                        Button("Add Simulator") { viewModel.addPump(.simulator) }
                     }
                     }
                 }
                 }
             }
             }

+ 4 - 3
FreeAPS/Sources/Modules/PumpConfig/View/PumpSetupView.swift

@@ -2,11 +2,10 @@ import LoopKit
 import LoopKitUI
 import LoopKitUI
 import MinimedKit
 import MinimedKit
 import MinimedKitUI
 import MinimedKitUI
+import MockKit
+import MockKitUI
 import OmniKit
 import OmniKit
 import OmniKitUI
 import OmniKitUI
-import RileyLinkBLEKit
-import RileyLinkKit
-import RileyLinkKitUI
 import SwiftUI
 import SwiftUI
 import UIKit
 import UIKit
 
 
@@ -25,6 +24,8 @@ extension PumpConfig {
                 setupViewController = MinimedPumpManager.setupViewController()
                 setupViewController = MinimedPumpManager.setupViewController()
             case .omnipod:
             case .omnipod:
                 setupViewController = OmnipodPumpManager.setupViewController()
                 setupViewController = OmnipodPumpManager.setupViewController()
+            case .simulator:
+                setupViewController = MockPumpManager.setupViewController()
             }
             }
 
 
             setupViewController.setupDelegate = setupDelegate
             setupViewController.setupDelegate = setupDelegate

+ 2 - 4
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -30,14 +30,12 @@ extension Settings {
                             .modal(for: .configEditor(file: OpenAPS.Settings.carbRatios), from: self)
                             .modal(for: .configEditor(file: OpenAPS.Settings.carbRatios), from: self)
                         Text("Temp targets").chevronCell()
                         Text("Temp targets").chevronCell()
                             .modal(for: .configEditor(file: OpenAPS.Settings.tempTargets), from: self)
                             .modal(for: .configEditor(file: OpenAPS.Settings.tempTargets), from: self)
-                        Text("Pump profile").chevronCell()
-                            .modal(for: .configEditor(file: OpenAPS.Settings.pumpProfile), from: self)
                     }
                     }
 
 
                     Group {
                     Group {
-                        Text("Profile").chevronCell().modal(for: .configEditor(file: OpenAPS.Settings.profile), from: self)
                         Text("Glucose").chevronCell().modal(for: .configEditor(file: OpenAPS.Monitor.glucose), from: self)
                         Text("Glucose").chevronCell().modal(for: .configEditor(file: OpenAPS.Monitor.glucose), from: self)
-                        Text("Meal").chevronCell().modal(for: .configEditor(file: OpenAPS.Monitor.meal), from: self)
+                        Text("Suggested").chevronCell()
+                            .modal(for: .configEditor(file: OpenAPS.Enact.suggested), from: self)
                     }
                     }
                 }
                 }
             }
             }