Procházet zdrojové kódy

Attempt to failproof bolus progress
* Send progress also as userInfo (when app in background); caution: we cannot influence priority of processing for userInfo
* Adapt behavior on watch
* Reset bolus progress when watch app opens by setting bolusProgress and activeBolusAmoount to 0 onAppear of TrioMainWatchView
* Calculate delivered units on iPhone, run it through pumpManager bolus rounding method
WIP

Deniz Cengiz před 1 rokem
rodič
revize
27ac229cbe

+ 2 - 5
Trio Watch App Extension/Views/BolusProgressOverlay.swift

@@ -17,9 +17,6 @@ struct BolusProgressOverlay: View {
     )
 
     var body: some View {
-        let bolusIncrement = Double(truncating: state.bolusIncrement as NSNumber)
-        let adjustedBolusAmount = floor(state.activeBolusAmount / bolusIncrement) * bolusIncrement
-
         VStack(spacing: 10) {
             VStack {
                 Text("Bolusing")
@@ -32,8 +29,8 @@ struct BolusProgressOverlay: View {
 
                 Text(String(
                     format: "%.2f U of %.2f U",
-                    state.bolusProgress * adjustedBolusAmount,
-                    adjustedBolusAmount
+                    state.deliveredAmount,
+                    state.activeBolusAmount
                 ))
                     .font(.footnote)
                     .foregroundStyle(.secondary)

+ 4 - 0
Trio Watch App Extension/Views/TrioMainWatchView.swift

@@ -91,6 +91,10 @@ struct TrioMainWatchView: View {
                 GlucoseChartView(glucoseValues: state.glucoseValues)
                     .tag(1)
             }
+            .onAppear {
+                state.bolusProgress = 0
+                state.activeBolusAmount = 0
+            }
             .background(trioBackgroundColor)
             .tabViewStyle(.verticalPage)
             .digitalCrownRotation($currentPage.doubleBinding(), from: 0, through: 1, by: 1)

+ 17 - 15
Trio Watch App Extension/WatchState.swift

@@ -31,11 +31,12 @@ import WatchConnectivity
     var carbsAmount: Int = 0
     var fatAmount: Int = 0
     var proteinAmount: Int = 0
-    var bolusAmount = 0.0
-    var activeBolusAmount = 0.0
-    var confirmationProgress = 0.0
+    var bolusAmount: Double = 0.0
+    var confirmationProgress: Double = 0.0
 
     var bolusProgress: Double = 0.0
+    var activeBolusAmount: Double = 0.0
+    var deliveredAmount: Double = 0.0
     var isBolusCanceled = false
 
     // Safety limits
@@ -65,8 +66,7 @@ import WatchConnectivity
     var isMealBolusCombo: Bool = false
 
     var showBolusProgressOverlay: Bool {
-        (!showAcknowledgmentBanner || !showCommsAnimation || !showCommsAnimation) && bolusProgress > 0 && bolusProgress < 1.0 &&
-            !isBolusCanceled
+        (!showAcknowledgmentBanner || !showCommsAnimation) && bolusProgress > 0 && bolusProgress < 1.0 && !isBolusCanceled
     }
 
     var recommendedBolus: Decimal = 0
@@ -140,10 +140,10 @@ import WatchConnectivity
             }
 
             if activationState == .activated {
-                self.forceConditionalWatchStateUpdate()
-
                 print("⌚️ Watch session activated with state: \(activationState.rawValue)")
 
+                self.forceConditionalWatchStateUpdate()
+
                 self.isReachable = session.isReachable
 
                 print("⌚️ Watch isReachable after activation: \(session.isReachable)")
@@ -204,7 +204,8 @@ import WatchConnectivity
                     // Handle bolus progress updates
         } else if
             let progress = message[WatchMessageKeys.bolusProgress] as? Double,
-            let activeBolusAmount = message[WatchMessageKeys.activeBolusAmount] as? Double
+            let activeBolusAmount = message[WatchMessageKeys.activeBolusAmount] as? Double,
+            let deliveredAmount = message[WatchMessageKeys.deliveredAmount] as? Double
         {
             DispatchQueue.main.async {
                 if !self.isBolusCanceled {
@@ -215,6 +216,8 @@ import WatchConnectivity
                     if self.activeBolusAmount == 0 {
                         self.activeBolusAmount = activeBolusAmount
                     }
+
+                    self.deliveredAmount = deliveredAmount
                 }
             }
             return
@@ -334,7 +337,7 @@ import WatchConnectivity
             }
         }
     }
-    
+
     /// Conditionally triggers a watch state update if the last known update was too long ago or has never occurred.
     ///
     /// This method checks the `lastWatchStateUpdate` timestamp to determine how many seconds
@@ -344,10 +347,10 @@ import WatchConnectivity
     ///
     /// it will show a syncing animation and request a new watch state update from the iPhone app.
     private func forceConditionalWatchStateUpdate() {
-        guard let lastUpdateTimestamp = self.lastWatchStateUpdate else {
+        guard let lastUpdateTimestamp = lastWatchStateUpdate else {
             // If there's no recorded timestamp, we must force a fresh update immediately.
-            self.showSyncingAnimation = true
-            self.requestWatchStateUpdate()
+            showSyncingAnimation = true
+            requestWatchStateUpdate()
             return
         }
 
@@ -356,13 +359,12 @@ import WatchConnectivity
 
         // If more than 15 seconds have elapsed since the last update, force an(other) update.
         if secondsSinceUpdate > 15 {
-            self.showSyncingAnimation = true
-            self.requestWatchStateUpdate()
+            showSyncingAnimation = true
+            requestWatchStateUpdate()
             return
         }
     }
 
-
     /// Handles incoming messages that either contain an acknowledgement or fresh watchState data  (<15 min)
     private func processWatchMessage(_ message: [String: Any]) {
         DispatchQueue.main.async {

+ 1 - 0
Trio/Sources/Models/WatchMessageKeys.swift

@@ -13,6 +13,7 @@ enum WatchMessageKeys {
     static let bolusCanceled = "bolusCanceled"
     static let bolusProgress = "bolusProgress"
     static let activeBolusAmount = "activeBolusAmount"
+    static let deliveredAmount = "deliveredAmount"
 
     // Recommendation Keys
     static let requestBolusRecommendation = "requestBolusRecommendation"

+ 34 - 6
Trio/Sources/Services/WatchManager/AppleWatchManager.swift

@@ -457,7 +457,7 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
 
     func session(_: WCSession, didReceiveMessage message: [String: Any]) {
         DispatchQueue.main.async { [weak self] in
-            // Prüfe zuerst auf Watch State Update Request
+            // Check Watch State Update Request first
             if let requestWatchUpdate = message[WatchMessageKeys.requestWatchUpdate] as? String,
                requestWatchUpdate == WatchMessageKeys.watchState
             {
@@ -527,7 +527,7 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
                     }
                     debug(.watchManager, "📱 Bolus cancelled from watch")
 
-                    // perform determine basal sync, otherwise you have could end up with too much iob when opening the calculator again
+                    // perform determine basal sync, otherwise you could end up with too much IOB when opening the calculator again
                     await self?.apsManager.determineBasalSync()
                 }
             }
@@ -905,16 +905,44 @@ final class BaseWatchManager: NSObject, WCSessionDelegate, Injectable, WatchMana
 
     /// Sends bolus progress updates to the Watch
     /// - Parameter progress: The current bolus progress as a Decimal
+//    private func sendBolusProgressToWatch(progress: Decimal?) async {
+//        guard let session = session, session.isReachable, let progress = progress else { return }
+//
+//        let message: [String: Any] = [
+//            WatchMessageKeys.bolusProgress: Double(truncating: progress as NSNumber),
+//            WatchMessageKeys.activeBolusAmount: activeBolusAmount
+//        ]
+//
+//        session.sendMessage(message, replyHandler: nil) { error in
+//            debug(.watchManager, "❌ Error sending bolus progress: \(error.localizedDescription)")
+//        }
+//    }
     private func sendBolusProgressToWatch(progress: Decimal?) async {
-        guard let session = session, session.isReachable, let progress = progress else { return }
+        guard let session = session, let progress = progress, let pumpManager = apsManager.pumpManager else { return }
 
         let message: [String: Any] = [
             WatchMessageKeys.bolusProgress: Double(truncating: progress as NSNumber),
-            WatchMessageKeys.activeBolusAmount: activeBolusAmount
+            WatchMessageKeys.activeBolusAmount: activeBolusAmount,
+            WatchMessageKeys.deliveredAmount: pumpManager
+                .roundToSupportedBolusVolume(units: activeBolusAmount * Double(truncating: progress as NSNumber))
         ]
+        // If the session is not yet activated, try to activate
+        if session.activationState != .activated {
+            session.activate()
+            // Then, queue data for eventual delivery in the background
+            session.transferUserInfo(message)
+            return
+        }
 
-        session.sendMessage(message, replyHandler: nil) { error in
-            debug(.watchManager, "❌ Error sending bolus progress: \(error.localizedDescription)")
+        // If we reach here, session should be .activated
+        if session.isReachable {
+            // Real-time ephemeral
+            session.sendMessage(message, replyHandler: nil) { error in
+                debug(.watchManager, "❌ Error sending bolus progress: \(error.localizedDescription)")
+            }
+        } else {
+            // Fallback to be double safe: queue userInfo for eventual delivery
+            session.transferUserInfo(message)
         }
     }