فهرست منبع

Merge pull request #89 from avouspierre/alpha

Add button to open the CGM app in settings view and fix heartbeat pump
bjornoleh 2 سال پیش
والد
کامیت
d5778779c0

+ 0 - 8
FreeAPS/Sources/APS/CGM/CGMType.swift

@@ -51,16 +51,8 @@ enum CGMType: String, JSON, CaseIterable, Identifiable {
             return URL(string: "xdripswift://")!
             return URL(string: "xdripswift://")!
         case .glucoseDirect:
         case .glucoseDirect:
             return URL(string: "libredirect://")!
             return URL(string: "libredirect://")!
-//        case .dexcomG5:
-//            return URL(string: "dexcomgcgm://")!
-//        case .dexcomG6:
-//            return URL(string: "dexcomg6://")!
-//        case .dexcomG7:
-//            return URL(string: "dexcomg7://")!
         case .simulator:
         case .simulator:
             return nil
             return nil
-//        case .libreTransmitter:
-//            return URL(string: "Open-iAPS://libre-transmitter")!
         case .plugin:
         case .plugin:
             return nil
             return nil
         }
         }

+ 1 - 1
FreeAPS/Sources/APS/CGM/PluginSource.swift

@@ -88,7 +88,7 @@ extension PluginSource: CGMManagerDelegate {
         dispatchPrecondition(condition: .onQueue(processQueue))
         dispatchPrecondition(condition: .onQueue(processQueue))
         debug(.deviceManager, " CGM Manager with identifier \(manager.pluginIdentifier) wants deletion")
         debug(.deviceManager, " CGM Manager with identifier \(manager.pluginIdentifier) wants deletion")
         // TODO:
         // TODO:
-        glucoseManager?.cgmGlucoseSourceType = nil
+        glucoseManager?.cgmGlucoseSourceType = .none
     }
     }
 
 
     func cgmManager(_ manager: CGMManager, hasNew readingResult: CGMReadingResult) {
     func cgmManager(_ manager: CGMManager, hasNew readingResult: CGMReadingResult) {

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

@@ -218,6 +218,7 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
 
 
     var glucoseManager: FetchGlucoseManager?
     var glucoseManager: FetchGlucoseManager?
     var cgmManager: CGMManagerUI?
     var cgmManager: CGMManagerUI?
+    var cgmType: CGMType = .enlite
 
 
     func fetchIfNeeded() -> AnyPublisher<[BloodGlucose], Never> {
     func fetchIfNeeded() -> AnyPublisher<[BloodGlucose], Never> {
         fetch(nil)
         fetch(nil)

+ 27 - 10
FreeAPS/Sources/APS/FetchGlucoseManager.swift

@@ -14,8 +14,8 @@ protocol FetchGlucoseManager: SourceInfoProvider {
     func removeCalibrations()
     func removeCalibrations()
     var glucoseSource: GlucoseSource! { get }
     var glucoseSource: GlucoseSource! { get }
     var cgmManager: CGMManagerUI? { get }
     var cgmManager: CGMManagerUI? { get }
-    var cgmGlucoseSourceType: CGMType? { get set }
-    var cgmGlucosePluginId: String? { get }
+    var cgmGlucoseSourceType: CGMType { get set }
+    var cgmGlucosePluginId: String { get }
     var settingsManager: SettingsManager! { get }
     var settingsManager: SettingsManager! { get }
     var shouldSyncToRemoteService: Bool { get }
     var shouldSyncToRemoteService: Bool { get }
 }
 }
@@ -40,8 +40,8 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
 
 
     private var lifetime = Lifetime()
     private var lifetime = Lifetime()
     private let timer = DispatchTimer(timeInterval: 1.minutes.timeInterval)
     private let timer = DispatchTimer(timeInterval: 1.minutes.timeInterval)
-    var cgmGlucoseSourceType: CGMType?
-    var cgmGlucosePluginId: String?
+    var cgmGlucoseSourceType: CGMType = .none
+    var cgmGlucosePluginId: String = ""
     var cgmManager: CGMManagerUI? {
     var cgmManager: CGMManagerUI? {
         didSet {
         didSet {
             rawCGMManager = cgmManager?.rawValue
             rawCGMManager = cgmManager?.rawValue
@@ -61,6 +61,10 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
 
 
     init(resolver: Resolver) {
     init(resolver: Resolver) {
         injectServices(resolver)
         injectServices(resolver)
+        // init at the start of the app
+        cgmGlucoseSourceType = settingsManager.settings.cgm
+        cgmGlucosePluginId = settingsManager.settings.cgmPluginIdentifier
+        // load cgmManager
         updateGlucoseSource(
         updateGlucoseSource(
             cgmGlucoseSourceType: settingsManager.settings.cgm,
             cgmGlucoseSourceType: settingsManager.settings.cgm,
             cgmGlucosePluginId: settingsManager.settings.cgmPluginIdentifier
             cgmGlucosePluginId: settingsManager.settings.cgmPluginIdentifier
@@ -82,10 +86,22 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
         )
         )
     }
     }
 
 
+    func saveConfigManager() {
+        guard let cgmM = cgmManager else {
+            return
+        }
+        // save the config in rawCGMManager
+        rawCGMManager = cgmM.rawValue
+
+        // sync with upload glucose
+        settingsManager.settings.uploadGlucose = cgmM.shouldSyncToRemoteService
+    }
+
     func updateGlucoseSource(cgmGlucoseSourceType: CGMType, cgmGlucosePluginId: String, newManager: CGMManagerUI?) {
     func updateGlucoseSource(cgmGlucoseSourceType: CGMType, cgmGlucosePluginId: String, newManager: CGMManagerUI?) {
         // if changed, remove all calibrations
         // if changed, remove all calibrations
         if self.cgmGlucoseSourceType != cgmGlucoseSourceType || self.cgmGlucosePluginId != cgmGlucosePluginId {
         if self.cgmGlucoseSourceType != cgmGlucoseSourceType || self.cgmGlucosePluginId != cgmGlucosePluginId {
             removeCalibrations()
             removeCalibrations()
+            cgmManager = nil
         }
         }
 
 
         self.cgmGlucoseSourceType = cgmGlucoseSourceType
         self.cgmGlucoseSourceType = cgmGlucoseSourceType
@@ -102,11 +118,12 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
             removeCalibrations()
             removeCalibrations()
         } else if self.cgmGlucoseSourceType == .plugin, cgmManager == nil, let rawCGMManager = rawCGMManager {
         } else if self.cgmGlucoseSourceType == .plugin, cgmManager == nil, let rawCGMManager = rawCGMManager {
             cgmManager = cgmManagerFromRawValue(rawCGMManager)
             cgmManager = cgmManagerFromRawValue(rawCGMManager)
+        } else {
+            saveConfigManager()
         }
         }
 
 
         switch self.cgmGlucoseSourceType {
         switch self.cgmGlucoseSourceType {
-        case nil,
-             .none?:
+        case .none:
             glucoseSource = nil
             glucoseSource = nil
         case .xdrip:
         case .xdrip:
             glucoseSource = AppGroupSource(from: "xDrip", cgmType: .xdrip)
             glucoseSource = AppGroupSource(from: "xDrip", cgmType: .xdrip)
@@ -127,7 +144,6 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
     /// Upload cgmManager from raw value
     /// Upload cgmManager from raw value
     func cgmManagerFromRawValue(_ rawValue: [String: Any]) -> CGMManagerUI? {
     func cgmManagerFromRawValue(_ rawValue: [String: Any]) -> CGMManagerUI? {
         guard let rawState = rawValue["state"] as? CGMManager.RawStateValue,
         guard let rawState = rawValue["state"] as? CGMManager.RawStateValue,
-              let cgmGlucosePluginId = self.cgmGlucosePluginId,
               let Manager = pluginCGMManager.getCGMManagerTypeByIdentifier(cgmGlucosePluginId)
               let Manager = pluginCGMManager.getCGMManagerTypeByIdentifier(cgmGlucosePluginId)
         else {
         else {
             return nil
             return nil
@@ -244,9 +260,8 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
     private func subscribe() {
     private func subscribe() {
         timer.publisher
         timer.publisher
             .receive(on: processQueue)
             .receive(on: processQueue)
-            .flatMap { _ -> AnyPublisher<[BloodGlucose], Never> in
+            .flatMap { [self] _ -> AnyPublisher<[BloodGlucose], Never> in
                 debug(.nightscout, "FetchGlucoseManager timer heartbeat")
                 debug(.nightscout, "FetchGlucoseManager timer heartbeat")
-                // self.updateGlucoseSource(manager: nil)
                 if let glucoseSource = self.glucoseSource {
                 if let glucoseSource = self.glucoseSource {
                     return glucoseSource.fetch(self.timer).eraseToAnyPublisher()
                     return glucoseSource.fetch(self.timer).eraseToAnyPublisher()
                 } else {
                 } else {
@@ -282,7 +297,9 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
     private func overcalibrate(entries: [BloodGlucose]) -> [BloodGlucose] {
     private func overcalibrate(entries: [BloodGlucose]) -> [BloodGlucose] {
         // overcalibrate
         // overcalibrate
         var overcalibration: ((Int) -> (Double))?
         var overcalibration: ((Int) -> (Double))?
-        processQueue.sync { overcalibration = calibrationService.calibrate }
+        processQueue.sync {
+            overcalibration = calibrationService.calibrate
+        }
 
 
         if let overcalibration = overcalibration {
         if let overcalibration = overcalibration {
             return entries.map { entry in
             return entries.map { entry in

+ 22 - 7
FreeAPS/Sources/Modules/CGM/CGMStateModel.swift

@@ -91,7 +91,7 @@ extension CGM {
                 .sink { [weak self] value in
                 .sink { [weak self] value in
                     guard let self = self else { return }
                     guard let self = self else { return }
                     guard self.cgmManager.cgmGlucoseSourceType != nil else {
                     guard self.cgmManager.cgmGlucoseSourceType != nil else {
-                        self.settingsManager.settings.cgm = .nightscout
+                        self.settingsManager.settings.cgm = .none
                         return
                         return
                     }
                     }
                     if value.type != self.settingsManager.settings.cgm ||
                     if value.type != self.settingsManager.settings.cgm ||
@@ -103,6 +103,7 @@ extension CGM {
                             cgmGlucoseSourceType: value.type,
                             cgmGlucoseSourceType: value.type,
                             cgmGlucosePluginId: value.id
                             cgmGlucosePluginId: value.id
                         )
                         )
+                        self.setupCGM = false
                     }
                     }
                 }
                 }
                 .store(in: &lifetime)
                 .store(in: &lifetime)
@@ -132,6 +133,26 @@ extension CGM {
                 }
                 }
                 .store(in: &lifetime)
                 .store(in: &lifetime)
         }
         }
+
+        func displayNameOfApp() -> String {
+            var nameOfApp = "Open Application"
+            switch cgmManager.cgmGlucoseSourceType {
+            case .plugin:
+                nameOfApp = "Open " + (cgmManager.cgmManager?.localizedTitle ?? "Application")
+            default:
+                nameOfApp = "Open " + (cgmManager.cgmGlucoseSourceType.displayName ?? "Application")
+            }
+            return nameOfApp
+        }
+
+        func urlOfApp() -> URL? {
+            switch cgmManager.cgmGlucoseSourceType {
+            case .plugin:
+                return cgmManager.cgmManager?.appURL
+            default:
+                return cgmManager.cgmGlucoseSourceType.appURL
+            }
+        }
     }
     }
 }
 }
 
 
@@ -149,9 +170,6 @@ extension CGM.StateModel: CompletionDelegate {
             cgmManager.updateGlucoseSource(cgmGlucoseSourceType: cgmCurrent.type, cgmGlucosePluginId: cgmCurrent.id)
             cgmManager.updateGlucoseSource(cgmGlucoseSourceType: cgmCurrent.type, cgmGlucosePluginId: cgmCurrent.id)
         }
         }
 
 
-        // refresh the upload options
-        settingsManager.settings.uploadGlucose = cgmManager.shouldSyncToRemoteService
-
         // update if required the Glucose source
         // update if required the Glucose source
         DispatchQueue.main.async {
         DispatchQueue.main.async {
             self.broadcaster.notify(GlucoseObserver.self, on: .main) {
             self.broadcaster.notify(GlucoseObserver.self, on: .main) {
@@ -163,9 +181,6 @@ extension CGM.StateModel: CompletionDelegate {
 
 
 extension CGM.StateModel: CGMManagerOnboardingDelegate {
 extension CGM.StateModel: CGMManagerOnboardingDelegate {
     func cgmManagerOnboarding(didCreateCGMManager manager: LoopKitUI.CGMManagerUI) {
     func cgmManagerOnboarding(didCreateCGMManager manager: LoopKitUI.CGMManagerUI) {
-        // update the setting of upload Glucose in services
-        settingsManager.settings.uploadGlucose = cgmManager.shouldSyncToRemoteService
-
         // update the glucose source
         // update the glucose source
         cgmManager.updateGlucoseSource(
         cgmManager.updateGlucoseSource(
             cgmGlucoseSourceType: cgmCurrent.type,
             cgmGlucoseSourceType: cgmCurrent.type,

+ 39 - 11
FreeAPS/Sources/Modules/CGM/View/CGMRootView.swift

@@ -29,6 +29,44 @@ extension CGM {
                             }
                             }
                         }
                         }
                     }
                     }
+
+                    if let cgmFetchManager = state.cgmManager {
+                        if let appURL = state.urlOfApp()
+                        {
+                            Section {
+                                Button {
+                                    UIApplication.shared.open(appURL, options: [:]) { success in
+                                        if !success {
+                                            self.router.alertMessage
+                                                .send(MessageContent(content: "Unable to open the app", type: .warning))
+                                        }
+                                    }
+                                }
+
+                                label: {
+                                    Label(state.displayNameOfApp(), systemImage: "waveform.path.ecg.rectangle").font(.title3) }
+                                    .frame(maxWidth: .infinity, alignment: .center)
+                                    .buttonStyle(.bordered)
+                            }
+                            .listRowBackground(Color.clear)
+                        } else if state.cgmCurrent.type == .nightscout && state.url != nil {
+                            Section {
+                                Button {
+                                    UIApplication.shared.open(state.url!, options: [:]) { success in
+                                        if !success {
+                                            self.router.alertMessage
+                                                .send(MessageContent(content: "No URL available", type: .warning))
+                                        }
+                                    }
+                                }
+                                label: { Label("Open URL", systemImage: "waveform.path.ecg.rectangle").font(.title3) }
+                                    .frame(maxWidth: .infinity, alignment: .center)
+                                    .buttonStyle(.bordered)
+                            }
+                            .listRowBackground(Color.clear)
+                        }
+                    }
+
                     if state.cgmCurrent.type == .plugin {
                     if state.cgmCurrent.type == .plugin {
                         Section {
                         Section {
                             Button("CGM Configuration") {
                             Button("CGM Configuration") {
@@ -54,17 +92,7 @@ extension CGM {
                         }
                         }
                     }
                     }
 
 
-                    if state.cgmCurrent.type == .nightscout {
-                        Section(header: Text("Nightscout")) {
-                            if state.url != nil {
-                                Button(state.url!.absoluteString) {
-                                    UIApplication.shared.open(state.url!, options: [:], completionHandler: nil)
-                                }
-                            } else {
-                                Text("You need to configure Nightscout URL")
-                            }
-                        }
-                    }
+                    // }
 
 
                     Section(header: Text("Calendar")) {
                     Section(header: Text("Calendar")) {
                         Toggle("Create events in calendar", isOn: $state.createCalendarEvents)
                         Toggle("Create events in calendar", isOn: $state.createCalendarEvents)