فهرست منبع

Fix Health integration (#142)

* Added blood glucose simulator

* First Integration HealthKit

* Update GlucoseSimulatorSource.swift

* Update project.pbxproj

* Update Info.plist

* Working ...

* Working...

* Add Watch App

* Working...

* Add HealthKit integration (only blood glucose)

* Some fix

* Add localization

* Update GlucoseSimulatorSource.swift

* Delete ConfigOverride.xcconfig

* Some fix

* Update project.pbxproj

* Update project.pbxproj

* Update project.pbxproj

* Update project.pbxproj

* Some fix

* Update project.pbxproj

* Update HealthKit integration

* Update Localizable.strings

* Update HealthKit integration

* Some fix

* Fix Health integration

Исправлена ошибка не добавления глюкозы из Здоровья, дублирования данных, поступивших из Здоровья (FreeAPS отправлял их в Здоровье новой записью).

* Update FetchGlucoseManager.swift

* Update Localizable.strings

* Update Localizable.strings

* Fix Future publisher and others

* Update HealthKitManager.swift

* Update HealthKitManager.swift
Jon B.M 4 سال پیش
والد
کامیت
d6186153d4

+ 1 - 0
FreeAPS/Sources/APS/CGM/DexcomSource.swift

@@ -26,6 +26,7 @@ final class DexcomSource: GlucoseSource {
         }
         .timeout(60, scheduler: processQueue, options: nil, customError: nil)
         .replaceError(with: [])
+        .replaceEmpty(with: [])
         .eraseToAnyPublisher()
     }
 

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

@@ -65,7 +65,7 @@ final class GlucoseSimulatorSource: GlucoseSource {
 
     func fetch() -> AnyPublisher<[BloodGlucose], Never> {
         guard canGenerateNewValues else {
-            return Empty().eraseToAnyPublisher()
+            return Just([]).eraseToAnyPublisher()
         }
 
         let glucoses = generator.getBloodGlucoses(

+ 1 - 0
FreeAPS/Sources/APS/CGM/LibreTransmitterSource.swift

@@ -39,6 +39,7 @@ final class BaseLibreTransmitterSource: LibreTransmitterSource, Injectable {
         }
         .timeout(60, scheduler: processQueue, options: nil, customError: nil)
         .replaceError(with: [])
+        .replaceEmpty(with: [])
         .eraseToAnyPublisher()
     }
 

+ 11 - 7
FreeAPS/Sources/APS/FetchGlucoseManager.swift

@@ -54,27 +54,31 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
     private func subscribe() {
         timer.publisher
             .receive(on: processQueue)
-            .flatMap { date -> AnyPublisher<(Date, Date, [BloodGlucose]), Never> in
+            .flatMap { date -> AnyPublisher<(Date, Date, [BloodGlucose], [BloodGlucose]), Never> in
                 debug(.nightscout, "FetchGlucoseManager heartbeat")
                 debug(.nightscout, "Start fetching glucose")
                 self.updateGlucoseSource()
-                return Publishers.CombineLatest3(
+                return Publishers.CombineLatest4(
                     Just(date),
                     Just(self.glucoseStorage.syncDate()),
-                    self.glucoseSource.fetch()
+                    self.glucoseSource.fetch(),
+                    self.healthKitManager.fetch()
                 )
                 .eraseToAnyPublisher()
             }
-            .sink { date, syncDate, glucose in
+            .sink { date, syncDate, glucose, glucoseFromHealth in
                 // Because of Spike dosn't respect a date query
-                let filteredByDate = glucose.filter { $0.dateString > syncDate }
+                let filteredByDate = (glucose + glucoseFromHealth).filter { $0.dateString > syncDate }
                 let filtered = self.glucoseStorage.filterTooFrequentGlucose(filteredByDate, at: syncDate)
-                if !filtered.isEmpty {
+                if filtered.isNotEmpty {
                     debug(.nightscout, "New glucose found")
                     self.glucoseStorage.storeGlucose(filtered)
                     self.apsManager.heartbeat(date: date, force: false)
                     self.nightscoutManager.uploadGlucose()
-                    self.healthKitManager.save(bloodGlucoses: filtered, completion: nil)
+                    let glucoseForHealth = filteredByDate.filter { !glucoseFromHealth.contains($0) }
+                    if glucoseForHealth.isNotEmpty {
+                        self.healthKitManager.save(bloodGlucoses: glucoseForHealth, completion: nil)
+                    }
                 }
             }
             .store(in: &lifetime)

+ 22 - 4
FreeAPS/Sources/Services/HealthKit/HealthKitManager.swift

@@ -98,6 +98,9 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
     }
 
     func save(bloodGlucoses: [BloodGlucose], completion: ((Result<Bool, Error>) -> Void)? = nil) {
+        guard settingsManager.settings.useAppleHealth,
+              bloodGlucoses.isNotEmpty else { return }
+
         for bgItem in bloodGlucoses {
             let bgQuantity = HKQuantity(
                 unit: .milligramsPerDeciliter,
@@ -145,14 +148,21 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
             }
 
             // loading only daily bg
-            let predicate = HKQuery.predicateForSamples(
+            let predicateByDate = HKQuery.predicateForSamples(
                 withStart: Date().addingTimeInterval(-1.days.timeInterval),
                 end: nil,
                 options: .strictStartDate
             )
+            // loading only not FreeAPS bg
+            let predicateByMeta = HKQuery.predicateForObjects(
+                withMetadataKey: "fromFreeAPSX",
+                operatorType: .notEqualTo,
+                value: 1
+            )
+            let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateByDate, predicateByMeta])
 
-            healthKitStore.execute(getQueryForDeletedBloodGlucose(sampleType: bgType, predicate: predicate))
-            healthKitStore.execute(getQueryForAddedBloodGlucose(sampleType: bgType, predicate: predicate))
+            healthKitStore.execute(getQueryForDeletedBloodGlucose(sampleType: bgType, predicate: predicateByDate))
+            healthKitStore.execute(getQueryForAddedBloodGlucose(sampleType: bgType, predicate: compoundPredicate))
         }
         healthKitStore.execute(query)
     }
@@ -200,7 +210,8 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
                         removingBGID.append($0.uuid.uuidString)
                     }
                 }
-                glucoseStorage.removeGlucose(byIDCollection: removingBGID)
+                glucoseStorage.removeGlucose(ids: removingBGID)
+                newGlucose = newGlucose.filter { !removingBGID.contains($0.id) }
             }
         }
         return query
@@ -259,6 +270,13 @@ final class BaseHealthKitManager: HealthKitManager, Injectable {
         }
         return query
     }
+
+    func fetch() -> AnyPublisher<[BloodGlucose], Never> {
+        guard settingsManager.settings.useAppleHealth else { return Just([]).eraseToAnyPublisher() }
+        let actualGlucose = newGlucose.filter { $0.dateString <= Date() }
+        newGlucose = newGlucose.filter { !actualGlucose.contains($0) }
+        return Just(actualGlucose).eraseToAnyPublisher()
+    }
 }
 
 enum HealthKitPermissionRequestStatus {