Преглед изворни кода

Use of Background process task

- use the IOS background process task to avoid the suspension of the execution of looping
- bug correction about healthkit Glucose
- minor correction
Pierre L пре 3 година
родитељ
комит
f2a3422245

+ 8 - 0
Dependencies/G7SensorKit/G7SensorKit.xcodeproj/project.pbxproj

@@ -55,6 +55,8 @@
 		C17F5156291EBD8600555EB5 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17F5155291EBD8600555EB5 /* Image.swift */; };
 		C17F5157291EBD9900555EB5 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17F513F291EB27D00555EB5 /* TimeInterval.swift */; };
 		C1E71720292D84FE00DA646F /* G7ProgressBarState.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E7171F292D84FE00DA646F /* G7ProgressBarState.swift */; };
+		CE70369C299F9AAB002D88AE /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE70369B299F9AAB002D88AE /* LoopKit.framework */; };
+		CE70369E299F9AAB002D88AE /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE70369D299F9AAB002D88AE /* LoopKitUI.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -148,6 +150,8 @@
 		C17F5155291EBD8600555EB5 /* Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
 		C17F5158291EBE7500555EB5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		C1E7171F292D84FE00DA646F /* G7ProgressBarState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = G7ProgressBarState.swift; sourceTree = "<group>"; };
+		CE70369B299F9AAB002D88AE /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		CE70369D299F9AAB002D88AE /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -155,6 +159,8 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CE70369C299F9AAB002D88AE /* LoopKit.framework in Frameworks */,
+				CE70369E299F9AAB002D88AE /* LoopKitUI.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -286,6 +292,8 @@
 		C17F5128291EAFA100555EB5 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				CE70369B299F9AAB002D88AE /* LoopKit.framework */,
+				CE70369D299F9AAB002D88AE /* LoopKitUI.framework */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";

+ 5 - 5
FreeAPS.xcodeproj/xcshareddata/xcschemes/FreeAPS X.xcscheme

@@ -23,9 +23,9 @@
       </BuildActionEntries>
    </BuildAction>
    <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      buildConfiguration = "Release"
+      selectedDebuggerIdentifier = ""
+      selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
          <TestableReference
@@ -42,8 +42,8 @@
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      selectedDebuggerIdentifier = ""
+      selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"

+ 5 - 0
FreeAPS/Resources/Info.plist

@@ -4,6 +4,10 @@
 <dict>
 	<key>AppGroupID</key>
 	<string>$(APP_GROUP_ID)</string>
+	<key>BGTaskSchedulerPermittedIdentifiers</key>
+	<array>
+		<string>com.freeapsx.background-task.critical-event-log</string>
+	</array>
 	<key>BuildBranch</key>
 	<string></string>
 	<key>CFBundleDevelopmentRegion</key>
@@ -83,6 +87,7 @@
 	<array>
 		<string>bluetooth-central</string>
 		<string>bluetooth-peripheral</string>
+		<string>processing</string>
 	</array>
 	<key>UIFileSharingEnabled</key>
 	<true/>

+ 24 - 3
FreeAPS/Sources/APS/APSManager.swift

@@ -83,6 +83,8 @@ final class BaseAPSManager: APSManager, Injectable {
 
     private var lifetime = Lifetime()
 
+    private var backGroundTaskID: UIBackgroundTaskIdentifier?
+
     var pumpManager: PumpManagerUI? {
         get { deviceDataManager.pumpManager }
         set { deviceDataManager.pumpManager = newValue }
@@ -189,7 +191,14 @@ final class BaseAPSManager: APSManager, Injectable {
             return
         }
 
-        debug(.apsManager, "Starting loop")
+        // start background time extension
+        backGroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Loop starting") {
+            guard let backgroundTask = self.backGroundTaskID else { return }
+            UIApplication.shared.endBackgroundTask(backgroundTask)
+            self.backGroundTaskID = .invalid
+        }
+
+        debug(.apsManager, "Starting loop with a delay of \(UIApplication.shared.backgroundTimeRemaining.rounded())")
 
         lastStartLoopDate = Date()
         var loopStatRecord = LoopStats(
@@ -240,6 +249,10 @@ final class BaseAPSManager: APSManager, Injectable {
 
         if let error = error {
             warning(.apsManager, "Loop failed with error: \(error.localizedDescription)")
+            if let backgroundTask = backGroundTaskID {
+                UIApplication.shared.endBackgroundTask(backgroundTask)
+                backGroundTaskID = .invalid
+            }
             processError(error)
         } else {
             debug(.apsManager, "Loop succeeded")
@@ -250,13 +263,21 @@ final class BaseAPSManager: APSManager, Injectable {
         loopStats(loopStatRecord: loopStatRecord)
 
         // Create a statistics.json. Don't run in backgound
-        if settings.displayStatistics, UIApplication.shared.applicationState != .background {
-            statistics()
+        DispatchQueue.main.async { [self] in
+            if settings.displayStatistics, UIApplication.shared.applicationState != .background {
+                statistics()
+            }
         }
 
         if settings.closedLoop {
             reportEnacted(received: error == nil)
         }
+
+        // end of the BG tasks
+        if let backgroundTask = backGroundTaskID {
+            UIApplication.shared.endBackgroundTask(backgroundTask)
+            backGroundTaskID = .invalid
+        }
     }
 
     private func verifyStatus() -> Error? {

+ 6 - 5
FreeAPS/Sources/APS/CGM/DexcomSourceG6.swift

@@ -25,6 +25,7 @@ final class DexcomSourceG6: GlucoseSource {
                 transmitterID: UserDefaults.standard
                     .dexcomTransmitterID ?? "000000"
             ))
+        cgmManager?.delegateQueue = processQueue
         cgmManager?.cgmManagerDelegate = self
     }
 
@@ -101,20 +102,20 @@ extension DexcomSourceG6: CGMManagerDelegate {
     }
 
     func cgmManager(_ manager: CGMManager, hasNew readingResult: CGMReadingResult) {
-        dispatchPrecondition(condition: .onQueue(.main))
+        dispatchPrecondition(condition: .onQueue(processQueue))
         processCGMReadingResult(manager, readingResult: readingResult) {
             debug(.deviceManager, "DEXCOM - Direct return done")
         }
     }
 
     func startDateToFilterNewData(for _: CGMManager) -> Date? {
-        dispatchPrecondition(condition: .onQueue(.main))
+        dispatchPrecondition(condition: .onQueue(processQueue))
         return glucoseStorage.lastGlucoseDate()
         //  return glucoseStore.latestGlucose?.startDate
     }
 
     func cgmManagerDidUpdateState(_ manager: CGMManager) {
-        dispatchPrecondition(condition: .onQueue(.main))
+        dispatchPrecondition(condition: .onQueue(processQueue))
         guard let g6Manager = manager as? TransmitterManager else {
             return
         }
@@ -127,7 +128,7 @@ extension DexcomSourceG6: CGMManagerDelegate {
     }
 
     func cgmManager(_: CGMManager, didUpdate status: CGMManagerStatus) {
-        DispatchQueue.main.async {
+        processQueue.async {
             if self.cgmHasValidSensorSession != status.hasValidSensorSession {
                 self.cgmHasValidSensorSession = status.hasValidSensorSession
             }
@@ -139,7 +140,7 @@ extension DexcomSourceG6: CGMManagerDelegate {
         readingResult: CGMReadingResult,
         completion: @escaping () -> Void
     ) {
-        debug(.deviceManager, "DEXCOM - Process CGM Reading Result launched")
+        debug(.deviceManager, "DEXCOM - Process CGM Reading Result launched with \(readingResult)")
         switch readingResult {
         case let .newData(values):
             let bloodGlucose = values.compactMap { newGlucoseSample -> BloodGlucose? in

+ 5 - 4
FreeAPS/Sources/APS/CGM/dexcomSourceG7.swift

@@ -21,6 +21,7 @@ final class DexcomSourceG7: GlucoseSource {
         self.glucoseManager = glucoseManager
         cgmManager = G7CGMManager()
         cgmManager?.cgmManagerDelegate = self
+        cgmManager?.delegateQueue = processQueue
     }
 
     func fetch(_: DispatchTimer?) -> AnyPublisher<[BloodGlucose], Never> {
@@ -85,20 +86,20 @@ extension DexcomSourceG7: CGMManagerDelegate {
     func recordRetractedAlert(_: LoopKit.Alert, at _: Date) {}
 
     func cgmManagerWantsDeletion(_ manager: CGMManager) {
-        dispatchPrecondition(condition: .onQueue(.main))
+        dispatchPrecondition(condition: .onQueue(processQueue))
         debug(.deviceManager, " CGM Manager with identifier \(manager.managerIdentifier) wants deletion")
         glucoseManager?.cgmGlucoseSourceType = nil
     }
 
     func cgmManager(_ manager: CGMManager, hasNew readingResult: CGMReadingResult) {
-        dispatchPrecondition(condition: .onQueue(.main))
+        dispatchPrecondition(condition: .onQueue(processQueue))
         processCGMReadingResult(manager, readingResult: readingResult) {
             debug(.deviceManager, "DEXCOM - Direct return done")
         }
     }
 
     func startDateToFilterNewData(for _: CGMManager) -> Date? {
-        dispatchPrecondition(condition: .onQueue(.main))
+        dispatchPrecondition(condition: .onQueue(processQueue))
         return glucoseStorage.lastGlucoseDate()
     }
 
@@ -110,7 +111,7 @@ extension DexcomSourceG7: CGMManagerDelegate {
     }
 
     func cgmManager(_: CGMManager, didUpdate status: CGMManagerStatus) {
-        DispatchQueue.main.async {
+        processQueue.async {
             if self.cgmHasValidSensorSession != status.hasValidSensorSession {
                 self.cgmHasValidSensorSession = status.hasValidSensorSession
             }

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

@@ -146,7 +146,6 @@ final class BaseFetchGlucoseManager: FetchGlucoseManager, Injectable {
             }
             .sink { glucose in
                 debug(.nightscout, "FetchGlucoseManager callback sensor")
-                guard glucose.isNotEmpty else { return }
                 Publishers.CombineLatest3(
                     Just(glucose),
                     Just(self.glucoseStorage.syncDate()),