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

Merge branch '0121'

Conflicts:
	FreeAPS/Sources/APS/Storage/GlucoseStorage.swift
Jon Mårtensson 5 лет назад
Родитель
Сommit
be52f6dfb3

+ 1 - 1
FreeAPS/Resources/Config.xcconfig

@@ -1 +1 @@
-BUILD_VERSION = 0.1.19
+BUILD_VERSION = 0.1.21

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

@@ -71,7 +71,7 @@ final class BaseAPSManager: APSManager, Injectable {
 
     private var openAPS: OpenAPS!
 
-    private var lifetime = Set<AnyCancellable>()
+    private var lifetime = Lifetime()
 
     var pumpManager: PumpManagerUI? {
         get { deviceDataManager.pumpManager }
@@ -174,9 +174,15 @@ final class BaseAPSManager: APSManager, Injectable {
         }
         let status = pump.status.pumpStatus
 
-        guard !status.bolusing, !status.suspended else {
-            debug(.apsManager, "Pump is bolusing or suspended")
-            processError(APSError.invalidPumpState(message: "Pump is bolusing or suspended"))
+        guard !status.bolusing else {
+            debug(.apsManager, "Pump is bolusing")
+            processError(APSError.invalidPumpState(message: "Pump is bolusing"))
+            return false
+        }
+
+        guard !status.suspended else {
+            debug(.apsManager, "Pump suspended")
+            processError(APSError.invalidPumpState(message: "Pump suspended"))
             return false
         }
 
@@ -259,7 +265,7 @@ final class BaseAPSManager: APSManager, Injectable {
     }
 
     func determineBasalSync() {
-        determineBasal().sink { _ in }.store(in: &lifetime)
+        determineBasal().cancellable().store(in: &lifetime)
     }
 
     func makeProfiles() -> AnyPublisher<Bool, Never> {
@@ -480,7 +486,6 @@ final class BaseAPSManager: APSManager, Injectable {
         guard let pump = pumpManager, verifyStatus(), bolusReporter == nil else {
             isLooping.send(false)
             debug(.apsManager, "Invalid pump state")
-            processError(APSError.invalidPumpState(message: "Pump is bolusing, suspended or not set"))
             return
         }
 

+ 31 - 35
FreeAPS/Sources/APS/DeviceDataManager.swift

@@ -34,7 +34,7 @@ private let staticPumpManagersByIdentifier: [String: PumpManagerUI.Type] = stati
 private let accessLock = NSRecursiveLock(label: "BaseDeviceDataManager.accessLock")
 
 final class BaseDeviceDataManager: DeviceDataManager, Injectable {
-    private let processQueue = DispatchQueue(label: "BaseDeviceDataManager.processQueue")
+    private let processQueue = DispatchQueue.markedQueue(label: "BaseDeviceDataManager.processQueue")
     @Injected() private var pumpHistoryStorage: PumpHistoryStorage!
     @Injected() private var storage: FileStorage!
     @Injected() private var broadcaster: Broadcaster!
@@ -65,13 +65,16 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
                     }
                     pumpExpiresAtDate.send(endTime)
                 }
-                pumpManager.setMustProvideBLEHeartbeat(true)
             } else {
                 pumpDisplayState.value = nil
             }
         }
     }
 
+    var hasBLEHeartbeat: Bool {
+        (pumpManager as? MockPumpManager) == nil
+    }
+
     let pumpDisplayState = CurrentValueSubject<PumpDisplayState?, Never>(nil)
     let pumpExpiresAtDate = CurrentValueSubject<Date?, Never>(nil)
     let pumpName = CurrentValueSubject<String, Never>("Pump")
@@ -88,37 +91,37 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
         }
     }
 
-    @SyncAccess(lock: accessLock) private var pumpUpdateInProgress = false
-
     func createBolusProgressReporter() -> DoseProgressReporter? {
         pumpManager?.createBolusProgressReporter(reportingOn: processQueue)
     }
 
     func heartbeat(date: Date, force: Bool) {
-        if force {
-            updatePumpData()
-            return
-        }
+        processQueue.safeSync {
+            if force {
+                updatePumpData()
+                return
+            }
 
-        var updateInterval: TimeInterval = 5.minutes.timeInterval
+            var updateInterval: TimeInterval = 4.5 * 60
 
-        switch lastHeartBeatTime.timeIntervalSince(date) {
-        case let interval where interval < -10.minutes.timeInterval:
-            break
-        case let interval where interval < -5.minutes.timeInterval:
-            updateInterval = 1.minutes.timeInterval
-        default:
-            break
-        }
+            switch date.timeIntervalSince(lastHeartBeatTime) {
+            case let interval where interval > 10.minutes.timeInterval:
+                break
+            case let interval where interval > 5.minutes.timeInterval:
+                updateInterval = 1.minutes.timeInterval
+            default:
+                break
+            }
 
-        let interval = date.timeIntervalSince(lastHeartBeatTime)
-        guard interval >= updateInterval else {
-            debug(.deviceManager, "Last hearbeat \(interval / 60) min ago, skip updating the pump data")
-            return
-        }
+            let interval = date.timeIntervalSince(lastHeartBeatTime)
+            guard interval >= updateInterval else {
+                debug(.deviceManager, "Last hearbeat \(interval / 60) min ago, skip updating the pump data")
+                return
+            }
 
-        lastHeartBeatTime = date
-        updatePumpData()
+            lastHeartBeatTime = date
+            updatePumpData()
+        }
     }
 
     private func updatePumpData() {
@@ -126,16 +129,11 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
             debug(.deviceManager, "Pump is not set, skip updating")
             return
         }
-        guard !pumpUpdateInProgress else {
-            debug(.deviceManager, "Pump update in progress, skip updating")
-            return
-        }
+
         debug(.deviceManager, "Start updating the pump data")
-        pumpUpdateInProgress = true
 
         pumpManager.ensureCurrentPumpData {
             debug(.deviceManager, "Pump Data updated")
-            self.pumpUpdateInProgress = false
         }
     }
 
@@ -173,8 +171,6 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
 
     func pumpManagerBLEHeartbeatDidFire(_: PumpManager) {
         debug(.deviceManager, "Pump Heartbeat")
-        pumpUpdateInProgress = false
-        heartbeat(date: Date(), force: false)
     }
 
     func pumpManagerMustProvideBLEHeartbeat(_: PumpManager) -> Bool {
@@ -182,6 +178,7 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
     }
 
     func pumpManager(_ pumpManager: PumpManager, didUpdate status: PumpManagerStatus, oldStatus _: PumpManagerStatus) {
+        dispatchPrecondition(condition: .onQueue(processQueue))
         debug(.deviceManager, "New pump status Bolus: \(status.bolusState)")
         debug(.deviceManager, "New pump status Basal: \(String(describing: status.basalDeliveryState))")
 
@@ -220,16 +217,16 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
     }
 
     func pumpManagerWillDeactivate(_: PumpManager) {
+        dispatchPrecondition(condition: .onQueue(processQueue))
         pumpManager = nil
-        pumpUpdateInProgress = false
     }
 
     func pumpManager(_: PumpManager, didUpdatePumpRecordsBasalProfileStartEvents _: Bool) {}
 
     func pumpManager(_: PumpManager, didError error: PumpManagerError) {
+        dispatchPrecondition(condition: .onQueue(processQueue))
         debug(.deviceManager, "error: \(error.localizedDescription), reason: \(String(describing: error.failureReason))")
         errorSubject.send(error)
-        pumpUpdateInProgress = false
     }
 
     func pumpManager(
@@ -270,7 +267,6 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
 
     func pumpManagerRecommendsLoop(_: PumpManager) {
         dispatchPrecondition(condition: .onQueue(processQueue))
-        pumpUpdateInProgress = false
         debug(.deviceManager, "Recomends loop")
         recommendsLoop.send()
     }

+ 2 - 1
FreeAPS/Sources/APS/FetchAnnouncementsManager.swift

@@ -12,7 +12,7 @@ final class BaseFetchAnnouncementsManager: FetchAnnouncementsManager, Injectable
     @Injected() var apsManager: APSManager!
     @Injected() var settingsManager: SettingsManager!
 
-    private var lifetime = Set<AnyCancellable>()
+    private var lifetime = Lifetime()
     private let timer = DispatchTimer(timeInterval: 1.minutes.timeInterval)
 
     init(resolver: Resolver) {
@@ -42,6 +42,7 @@ final class BaseFetchAnnouncementsManager: FetchAnnouncementsManager, Injectable
                 }
             }
             .store(in: &lifetime)
+        timer.fire()
         timer.resume()
     }
 }

+ 3 - 2
FreeAPS/Sources/APS/FetchGlucoseManager.swift

@@ -11,7 +11,7 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
     @Injected() var nightscoutManager: NightscoutManager!
     @Injected() var apsManager: APSManager!
 
-    private var lifetime = Set<AnyCancellable>()
+    private var lifetime = Lifetime()
     private let timer = DispatchTimer(timeInterval: 1.minutes.timeInterval)
 
     init(resolver: Resolver) {
@@ -44,10 +44,11 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
                 if !filtered.isEmpty {
                     debug(.nightscout, "New glucose found")
                     self.glucoseStorage.storeGlucose(filtered)
-                    self.apsManager.heartbeat(date: date, force: true)
+                    self.apsManager.heartbeat(date: date, force: false)
                 }
             }
             .store(in: &lifetime)
+        timer.fire()
         timer.resume()
     }
 

+ 2 - 1
FreeAPS/Sources/APS/FetchTreatmentsManager.swift

@@ -11,7 +11,7 @@ final class BaseFetchTreatmentsManager: FetchTreatmentsManager, Injectable {
     @Injected() var tempTargetsStorage: TempTargetsStorage!
     @Injected() var carbsStorage: CarbsStorage!
 
-    private var lifetime = Set<AnyCancellable>()
+    private var lifetime = Lifetime()
     private let timer = DispatchTimer(timeInterval: 1.minutes.timeInterval)
 
     init(resolver: Resolver) {
@@ -41,6 +41,7 @@ final class BaseFetchTreatmentsManager: FetchTreatmentsManager, Injectable {
                 }
             }
             .store(in: &lifetime)
+        timer.fire()
         timer.resume()
     }
 }

+ 1 - 1
FreeAPS/Sources/APS/Storage/GlucoseStorage.swift

@@ -87,7 +87,7 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable {
 
         return Array(
             last5
-                .compactMap { $0.filtered ?? Decimal($0.sgv ?? 0) }
+            compactMap { $0.filtered ?? 0 }
                 .filter { $0 != 0 }
                 .uniqued()
         ).count != 1

+ 2 - 2
FreeAPS/Sources/Helpers/DispatchTimer.swift

@@ -19,12 +19,12 @@ class DispatchTimer {
         let timer = DispatchSource.makeTimerSource(queue: queue)
         timer.schedule(deadline: .now() + timeInterval, repeating: timeInterval)
         timer.setEventHandler(handler: { [weak self] in
-            self?.fireEvent()
+            self?.fire()
         })
         return timer
     }()
 
-    private func fireEvent() {
+    func fire() {
         subject.send(Date())
         eventHandler?()
     }

+ 14 - 0
FreeAPS/Sources/Helpers/Publisher.swift

@@ -27,3 +27,17 @@ extension Publisher {
         zip(dropFirst()).eraseToAnyPublisher()
     }
 }
+
+extension Publisher {
+    func cancellable() -> some Cancellable {
+        sink { _ in } receiveValue: { _ in }
+    }
+}
+
+extension Publisher where Failure == Never {
+    func cancellable() -> some Cancellable {
+        sink { _ in }
+    }
+}
+
+typealias Lifetime = Set<AnyCancellable>

+ 2 - 2
FreeAPS/Sources/Modules/AutotuneConfig/AutotuneConfigViewModel.swift

@@ -27,7 +27,7 @@ extension AutotuneConfig {
                     self.settingsManager.settings.useAutotune = use
                     return self.apsManager.makeProfiles()
                 }
-                .sink { _ in }
+                .cancellable()
                 .store(in: &lifetime)
         }
 
@@ -47,7 +47,7 @@ extension AutotuneConfig {
             provider.deleteAutotune()
             autotune = nil
             apsManager.makeProfiles()
-                .sink { _ in }
+                .cancellable()
                 .store(in: &lifetime)
         }
     }

+ 1 - 1
FreeAPS/Sources/Modules/Base/BaseProvider.swift

@@ -7,7 +7,7 @@ protocol Provider {
 }
 
 class BaseProvider: Provider, Injectable {
-    var lifetime = Set<AnyCancellable>()
+    var lifetime = Lifetime()
     @Injected() var authorizationManager: AuthorizationManager!
     @Injected() var deviceManager: DeviceDataManager!
     @Injected() var storage: FileStorage!

+ 1 - 1
FreeAPS/Sources/Modules/Base/BaseViewModel.swift

@@ -12,7 +12,7 @@ protocol ViewModel {
 class BaseViewModel<Provider>: ViewModel, Injectable where Provider: FreeAPS.Provider {
     let resolver: Resolver
     let provider: Provider
-    var lifetime = Set<AnyCancellable>()
+    var lifetime = Lifetime()
     @Injected() var router: Router!
 
     required init(provider: Provider, resolver: Resolver) {

+ 1 - 1
FreeAPS/Sources/Services/AuthorizationManager/AuthorizationManager.swift

@@ -17,7 +17,7 @@ final class BaseAuthorizationManager: AuthorizationManager, Injectable {
 
     let credentials = CurrentValueSubject<Credentials?, Never>(nil)
 
-    private var lifetime = Set<AnyCancellable>()
+    private var lifetime = Lifetime()
 
     @Injected() private var keychain: Keychain!
 

+ 1 - 1
FreeAPS/Sources/Services/Network/NightscoutManager.swift

@@ -27,7 +27,7 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
 
     private let processQueue = DispatchQueue(label: "BaseNetworkManager.processQueue")
 
-    private var lifetime = Set<AnyCancellable>()
+    private var lifetime = Lifetime()
 
     private var isNetworkReachable: Bool {
         reachabilityManager.isReachable