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

Merge branch 'beta-fixes-3' of github.com:nightscout/Trio-dev into beta-fixes-3

Deniz Cengiz пре 1 година
родитељ
комит
14d03fa31d

+ 14 - 0
Model/Helper/AdjustmentStored+Helper.swift

@@ -0,0 +1,14 @@
+import CoreData
+import Foundation
+
+extension NSPredicate {
+    static var lastActiveAdjustmentNotYetUploadedToNightscout: NSPredicate {
+        let date = Date.oneDayAgo
+        return NSPredicate(
+            format: "date >= %@ AND enabled == %@ AND isUploadedToNS == %@",
+            date as NSDate,
+            true as NSNumber,
+            false as NSNumber
+        )
+    }
+}

+ 0 - 10
Model/Helper/OverrideStored+helper.swift

@@ -14,16 +14,6 @@ extension NSPredicate {
             true as NSNumber
         )
     }
-
-    static var lastActiveOverrideNotYetUploadedToNightscout: NSPredicate {
-        let date = Date.oneDayAgo
-        return NSPredicate(
-            format: "date >= %@ AND enabled == %@ AND isUploadedToNS == %@",
-            date as NSDate,
-            true as NSNumber,
-            false as NSNumber
-        )
-    }
 }
 
 extension OverrideStored {

+ 87 - 3
Model/Helper/PumpEvent+helper.swift

@@ -102,7 +102,7 @@ struct BolusDTO: Codable {
     var isExternal: Bool
     var isSMB: Bool
     var duration: Int
-    var _type: String = "Bolus"
+    var _type: String = EventType.bolus.rawValue
 }
 
 struct TempBasalDTO: Codable {
@@ -110,14 +110,14 @@ struct TempBasalDTO: Codable {
     var timestamp: String
     var temp: String
     var rate: Double
-    var _type: String = "TempBasal"
+    var _type: String = EventType.tempBasal.rawValue
 }
 
 struct TempBasalDurationDTO: Codable {
     var id: String
     var timestamp: String
     var duration: Int
-    var _type: String = "TempBasalDuration"
+    var _type: String = EventType.tempBasalDuration.rawValue
 
     private enum CodingKeys: String, CodingKey {
         case id
@@ -127,11 +127,39 @@ struct TempBasalDurationDTO: Codable {
     }
 }
 
+struct SuspendDTO: Codable {
+    var id: String
+    var timestamp: String
+    var _type: String = EventType.pumpSuspend.rawValue
+}
+
+struct ResumeDTO: Codable {
+    var id: String
+    var timestamp: String
+    var _type: String = EventType.pumpResume.rawValue
+}
+
+struct RewindDTO: Codable {
+    var id: String
+    var timestamp: String
+    var _type: String = EventType.rewind.rawValue
+}
+
+struct PrimeDTO: Codable {
+    var id: String
+    var timestamp: String
+    var _type: String = EventType.prime.rawValue
+}
+
 // Mask distinct DTO subtypes with a common enum that conforms to Encodable
 enum PumpEventDTO: Encodable {
     case bolus(BolusDTO)
     case tempBasal(TempBasalDTO)
     case tempBasalDuration(TempBasalDurationDTO)
+    case suspend(SuspendDTO)
+    case resume(ResumeDTO)
+    case rewind(RewindDTO)
+    case prime(PrimeDTO)
 
     func encode(to encoder: Encoder) throws {
         switch self {
@@ -141,6 +169,14 @@ enum PumpEventDTO: Encodable {
             try tempBasal.encode(to: encoder)
         case let .tempBasalDuration(tempBasalDuration):
             try tempBasalDuration.encode(to: encoder)
+        case let .suspend(suspend):
+            try suspend.encode(to: encoder)
+        case let .resume(resume):
+            try resume.encode(to: encoder)
+        case let .rewind(rewind):
+            try rewind.encode(to: encoder)
+        case let .prime(prime):
+            try prime.encode(to: encoder)
         }
     }
 }
@@ -195,4 +231,52 @@ extension PumpEventStored {
         )
         return .tempBasalDuration(tempBasalDurationDTO)
     }
+
+    func toPumpSuspendDTO() -> PumpEventDTO? {
+        guard let id = id, let timestamp = timestamp, let type = type, type == EventType.pumpSuspend.rawValue else {
+            return nil
+        }
+
+        let suspendDTO = SuspendDTO(
+            id: id,
+            timestamp: PumpEventStored.dateFormatter.string(from: timestamp)
+        )
+        return .suspend(suspendDTO)
+    }
+
+    func toPumpResumeDTO() -> PumpEventDTO? {
+        guard let id = id, let timestamp = timestamp, let type = type, type == EventType.pumpResume.rawValue else {
+            return nil
+        }
+
+        let resumeDTO = ResumeDTO(
+            id: id,
+            timestamp: PumpEventStored.dateFormatter.string(from: timestamp)
+        )
+        return .resume(resumeDTO)
+    }
+
+    func toRewindDTO() -> PumpEventDTO? {
+        guard let id = id, let timestamp = timestamp, let type = type, type == EventType.rewind.rawValue else {
+            return nil
+        }
+
+        let rewindDTO = RewindDTO(
+            id: id,
+            timestamp: PumpEventStored.dateFormatter.string(from: timestamp)
+        )
+        return .rewind(rewindDTO)
+    }
+
+    func toPrimeDTO() -> PumpEventDTO? {
+        guard let id = id, let timestamp = timestamp, let type = type, type == EventType.prime.rawValue else {
+            return nil
+        }
+
+        let primeDTO = PrimeDTO(
+            id: id,
+            timestamp: PumpEventStored.dateFormatter.string(from: timestamp)
+        )
+        return .prime(primeDTO)
+    }
 }

+ 4 - 0
Trio.xcodeproj/project.pbxproj

@@ -212,6 +212,7 @@
 		491D6FBE2D56741C00C49F67 /* TempTargetRunStored+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491D6FB92D56741C00C49F67 /* TempTargetRunStored+CoreDataClass.swift */; };
 		491D6FBF2D56741C00C49F67 /* TempTargetRunStored+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491D6FBA2D56741C00C49F67 /* TempTargetRunStored+CoreDataProperties.swift */; };
 		491D6FC02D56741C00C49F67 /* TempTargetStored+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491D6FBB2D56741C00C49F67 /* TempTargetStored+CoreDataClass.swift */; };
+		49B9B57F2D5768D2009C6B59 /* AdjustmentStored+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49B9B57E2D5768D2009C6B59 /* AdjustmentStored+Helper.swift */; };
 		5075C1608E6249A51495C422 /* TargetsEditorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDEA2DC60EDE0A3CA54DC73 /* TargetsEditorProvider.swift */; };
 		53F2382465BF74DB1A967C8B /* PumpConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8630D58BDAD6D9C650B9B39 /* PumpConfigProvider.swift */; };
 		581516A42BCED84A00BF67D7 /* DebuggingIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581516A32BCED84A00BF67D7 /* DebuggingIdentifiers.swift */; };
@@ -942,6 +943,7 @@
 		491D6FBA2D56741C00C49F67 /* TempTargetRunStored+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TempTargetRunStored+CoreDataProperties.swift"; sourceTree = "<group>"; };
 		491D6FBB2D56741C00C49F67 /* TempTargetStored+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TempTargetStored+CoreDataClass.swift"; sourceTree = "<group>"; };
 		491D6FBC2D56741C00C49F67 /* TempTargetStored+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TempTargetStored+CoreDataProperties.swift"; sourceTree = "<group>"; };
+		49B9B57E2D5768D2009C6B59 /* AdjustmentStored+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentStored+Helper.swift"; sourceTree = "<group>"; };
 		4DD795BA46B193644D48138C /* TargetsEditorRootView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TargetsEditorRootView.swift; sourceTree = "<group>"; };
 		505E09DC17A0C3D0AF4B66FE /* ISFEditorStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ISFEditorStateModel.swift; sourceTree = "<group>"; };
 		581516A32BCED84A00BF67D7 /* DebuggingIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggingIdentifiers.swift; sourceTree = "<group>"; };
@@ -2354,6 +2356,7 @@
 		5825D1622BD405AE00F36E9B /* Helper */ = {
 			isa = PBXGroup;
 			children = (
+				49B9B57E2D5768D2009C6B59 /* AdjustmentStored+Helper.swift */,
 				581516A82BCEEDF800BF67D7 /* NSPredicates.swift */,
 				583684052BD178DB00070A60 /* GlucoseStored+helper.swift */,
 				58F107732BD1A4D000B1A680 /* Determination+helper.swift */,
@@ -3962,6 +3965,7 @@
 				DD1745222C55524800211FAC /* SMBSettingsProvider.swift in Sources */,
 				BF1667ADE69E4B5B111CECAE /* ManualTempBasalProvider.swift in Sources */,
 				583684062BD178DB00070A60 /* GlucoseStored+helper.swift in Sources */,
+				49B9B57F2D5768D2009C6B59 /* AdjustmentStored+Helper.swift in Sources */,
 				F90692D6274B9A450037068D /* HealthKitStateModel.swift in Sources */,
 				BD1661312B82ADAB00256551 /* CustomProgressView.swift in Sources */,
 				C967DACD3B1E638F8B43BE06 /* ManualTempBasalStateModel.swift in Sources */,

+ 9 - 3
Trio/Sources/APS/APSManager.swift

@@ -22,7 +22,7 @@ protocol APSManager {
     func enactTempBasal(rate: Double, duration: TimeInterval) async
     func determineBasal() async -> Bool
     func determineBasalSync() async
-    func simulateDetermineBasal(carbs: Decimal, iob: Decimal) async -> Determination?
+    func simulateDetermineBasal(simulatedCarbsAmount: Decimal, simulatedBolusAmount: Decimal) async -> Determination?
     func roundBolus(amount: Decimal) -> Decimal
     var lastError: CurrentValueSubject<Error?, Never> { get }
     func cancelBolus(_ callback: ((Bool, String) -> Void)?) async
@@ -413,10 +413,16 @@ final class BaseAPSManager: APSManager, Injectable {
         _ = await determineBasal()
     }
 
-    func simulateDetermineBasal(carbs: Decimal, iob: Decimal) async -> Determination? {
+    func simulateDetermineBasal(simulatedCarbsAmount: Decimal, simulatedBolusAmount: Decimal) async -> Determination? {
         do {
             let temp = await fetchCurrentTempBasal(date: Date.now)
-            return try await openAPS.determineBasal(currentTemp: temp, clock: Date(), carbs: carbs, iob: iob, simulation: true)
+            return try await openAPS.determineBasal(
+                currentTemp: temp,
+                clock: Date(),
+                simulatedCarbsAmount: simulatedCarbsAmount,
+                simulatedBolusAmount: simulatedBolusAmount,
+                simulation: true
+            )
         } catch {
             debugPrint(
                 "\(DebuggingIdentifiers.failed) \(#file) \(#function) Error occurred in invokeDummyDetermineBasalSync: \(error)"

+ 25 - 10
Trio/Sources/APS/OpenAPS/OpenAPS.swift

@@ -189,7 +189,10 @@ final class OpenAPS {
         }
     }
 
-    private func parsePumpHistory(_ pumpHistoryObjectIDs: [NSManagedObjectID], iob: Decimal? = nil) async -> String {
+    private func parsePumpHistory(
+        _ pumpHistoryObjectIDs: [NSManagedObjectID],
+        simulatedBolusAmount: Decimal? = nil
+    ) async -> String {
         // Return an empty JSON object if the list of object IDs is empty
         guard !pumpHistoryObjectIDs.isEmpty else { return "{}" }
 
@@ -199,9 +202,9 @@ final class OpenAPS {
             var dtos = self.loadAndMapPumpEvents(pumpHistoryObjectIDs)
 
             // Optionally add the IOB as a DTO
-            if let iob = iob {
-                let iobDTO = self.createIOBDTO(iob: iob)
-                dtos.insert(iobDTO, at: 0)
+            if let simulatedBolusAmount = simulatedBolusAmount {
+                let simulatedBolusDTO = self.createSimulatedBolusDTO(simulatedBolusAmount: simulatedBolusAmount)
+                dtos.insert(simulatedBolusDTO, at: 0)
             }
 
             // Convert the DTOs to JSON
@@ -226,12 +229,24 @@ final class OpenAPS {
             if let tempBasalDTO = event.toTempBasalDTOEnum() {
                 eventDTOs.append(tempBasalDTO)
             }
+            if let pumpSuspendDTO = event.toPumpSuspendDTO() {
+                eventDTOs.append(pumpSuspendDTO)
+            }
+            if let pumpResumeDTO = event.toPumpResumeDTO() {
+                eventDTOs.append(pumpResumeDTO)
+            }
+            if let rewindDTO = event.toRewindDTO() {
+                eventDTOs.append(rewindDTO)
+            }
+            if let primeDTO = event.toPrimeDTO() {
+                eventDTOs.append(primeDTO)
+            }
             return eventDTOs
         }
         return dtos
     }
 
-    private func createIOBDTO(iob: Decimal) -> PumpEventDTO {
+    private func createSimulatedBolusDTO(simulatedBolusAmount: Decimal) -> PumpEventDTO {
         let oneSecondAgo = Calendar.current
             .date(
                 byAdding: .second,
@@ -243,7 +258,7 @@ final class OpenAPS {
         let bolusDTO = BolusDTO(
             id: UUID().uuidString,
             timestamp: dateFormatted,
-            amount: Double(iob),
+            amount: Double(simulatedBolusAmount),
             isExternal: false,
             isSMB: true,
             duration: 0,
@@ -255,8 +270,8 @@ final class OpenAPS {
     func determineBasal(
         currentTemp: TempBasal,
         clock: Date = Date(),
-        carbs: Decimal? = nil,
-        iob: Decimal? = nil,
+        simulatedCarbsAmount: Decimal? = nil,
+        simulatedBolusAmount: Decimal? = nil,
         simulation: Bool = false
     ) async throws -> Determination? {
         debug(.openAPS, "Start determineBasal")
@@ -266,7 +281,7 @@ final class OpenAPS {
 
         // Perform asynchronous calls in parallel
         async let pumpHistoryObjectIDs = fetchPumpHistoryObjectIDs() ?? []
-        async let carbs = fetchAndProcessCarbs(additionalCarbs: carbs ?? 0)
+        async let carbs = fetchAndProcessCarbs(additionalCarbs: simulatedCarbsAmount ?? 0)
         async let glucose = fetchAndProcessGlucose()
         async let oref2 = oref2()
         async let profileAsync = loadFileFromStorageAsync(name: Settings.profile)
@@ -287,7 +302,7 @@ final class OpenAPS {
             reservoir,
             preferences
         ) = await (
-            parsePumpHistory(await pumpHistoryObjectIDs, iob: iob),
+            parsePumpHistory(await pumpHistoryObjectIDs, simulatedBolusAmount: simulatedBolusAmount),
             carbs,
             glucose,
             oref2,

+ 1 - 1
Trio/Sources/APS/Storage/OverrideStorage.swift

@@ -210,7 +210,7 @@ final class BaseOverrideStorage: @preconcurrency OverrideStorage, Injectable {
         let results = await CoreDataStack.shared.fetchEntitiesAsync(
             ofType: OverrideStored.self,
             onContext: backgroundContext,
-            predicate: NSPredicate.lastActiveOverrideNotYetUploadedToNightscout,
+            predicate: NSPredicate.lastActiveAdjustmentNotYetUploadedToNightscout,
             key: "date",
             ascending: false
         )

+ 3 - 3
Trio/Sources/APS/Storage/TempTargetsStorage.swift

@@ -14,7 +14,7 @@ protocol TempTargetsStorage {
     func fetchScheduledTempTargets() async -> [NSManagedObjectID]
     func fetchScheduledTempTarget(for targetDate: Date) async -> [NSManagedObjectID]
     func copyRunningTempTarget(_ tempTarget: TempTargetStored) async -> NSManagedObjectID
-    func deleteOverridePreset(_ objectID: NSManagedObjectID) async
+    func deleteTempTargetPreset(_ objectID: NSManagedObjectID) async
     func loadLatestTempTargetConfigurations(fetchLimit: Int) async -> [NSManagedObjectID]
     func syncDate() -> Date
     func recent() -> [TempTarget]
@@ -216,7 +216,7 @@ final class BaseTempTargetsStorage: TempTargetsStorage, Injectable {
         return newTempTarget.objectID
     }
 
-    @MainActor func deleteOverridePreset(_ objectID: NSManagedObjectID) async {
+    @MainActor func deleteTempTargetPreset(_ objectID: NSManagedObjectID) async {
         await CoreDataStack.shared.deleteObject(identifiedBy: objectID)
     }
 
@@ -246,7 +246,7 @@ final class BaseTempTargetsStorage: TempTargetsStorage, Injectable {
         let results = await CoreDataStack.shared.fetchEntitiesAsync(
             ofType: TempTargetStored.self,
             onContext: backgroundContext,
-            predicate: NSPredicate.lastActiveOverrideNotYetUploadedToNightscout, // TODO: create adjustment predicate (OR+TT)
+            predicate: NSPredicate.lastActiveAdjustmentNotYetUploadedToNightscout,
             key: "date",
             ascending: false
         )

+ 3 - 3
Trio/Sources/Modules/Adjustments/AdjustmentsStateModel+Extensions/AdjustmentsStateModel+TempTargets.swift

@@ -254,7 +254,7 @@ extension Adjustments.StateModel {
             )
             tempTargetStorage.saveTempTargetsToStorage([tempTarget])
         } catch {
-            debugPrint("\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to enact Override Preset")
+            debugPrint("\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to enact TempTarget Preset")
         }
     }
 
@@ -313,7 +313,7 @@ extension Adjustments.StateModel {
 
     /// Duplicates the current preset and cancels the previous one.
     @MainActor func duplicateTempTargetPresetAndCancelPreviousTempTarget() async {
-        // We get the current active Preset by using currentActiveTempTarget which can either be a Preset or a custom Override
+        // We get the current active Preset by using currentActiveTempTarget which can either be a Preset or a custom TempTarget
         guard let tempTargetPresetToDuplicate = currentActiveTempTarget,
               tempTargetPresetToDuplicate.isPreset == true else { return }
 
@@ -344,7 +344,7 @@ extension Adjustments.StateModel {
 
     /// Deletes a Temp Target preset.
     func invokeTempTargetPresetDeletion(_ objectID: NSManagedObjectID) async {
-        await tempTargetStorage.deleteOverridePreset(objectID)
+        await tempTargetStorage.deleteTempTargetPreset(objectID)
         setupTempTargetPresetsArray()
     }
 

+ 1 - 1
Trio/Sources/Modules/Treatments/TreatmentsStateModel.swift

@@ -788,7 +788,7 @@ extension Treatments.StateModel {
         } else {
             simulatedDetermination = await Task { [self] in
                 debug(.bolusState, "calling simulateDetermineBasal to get forecast data")
-                return await apsManager.simulateDetermineBasal(carbs: carbs, iob: amount)
+                return await apsManager.simulateDetermineBasal(simulatedCarbsAmount: carbs, simulatedBolusAmount: amount)
             }.value
         }
 

+ 1 - 0
Trio/Sources/Shortcuts/TempPresets/TempPresetsIntentRequest.swift

@@ -167,6 +167,7 @@ final class TempPresetsIntentRequest: BaseIntentsRequest {
 
     func cancelTempTarget() async {
         await disableAllActiveTempTargets(createTempTargetRunEntry: true, shouldStartBackgroundTask: true)
+        tempTargetsStorage.saveTempTargetsToStorage([TempTarget.cancel(at: Date().addingTimeInterval(-1))])
     }
 
     @MainActor func disableAllActiveTempTargets(