소스 검색

Extend WatchLogger; add lots of logging

Deniz Cengiz 1 년 전
부모
커밋
c00673a1f6
3개의 변경된 파일114개의 추가작업 그리고 137개의 파일을 삭제
  1. 10 3
      Trio Watch App Extension/WatchLogger.swift
  2. 86 30
      Trio Watch App Extension/WatchState+Requests.swift
  3. 18 104
      Trio Watch App Extension/WatchState.swift

+ 10 - 3
Trio Watch App Extension/WatchLogger.swift

@@ -24,9 +24,16 @@ final class WatchLogger {
         }
     }
 
-    func log(_ message: String) {
-        let timestamp = ISO8601DateFormatter().string(from: Date())
-        let entry = "[\(timestamp)] \(message)"
+    private var dateFormatter: DateFormatter {
+        let dateFormatter = DateFormatter()
+        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
+        return dateFormatter
+    }
+
+    func log(_ message: String, function: String = #function, file: String = #fileID, line: Int = #line) {
+        let shortFile = (file as NSString).lastPathComponent
+        let timestamp = dateFormatter.string(from: Date())
+        let entry = "[\(timestamp)] [\(shortFile):\(line)] \(function) → \(message)"
         logs.append(entry)
 
         if logs.count > maxEntries {

+ 86 - 30
Trio Watch App Extension/WatchState+Requests.swift

@@ -8,20 +8,28 @@ extension WatchState {
     /// - Parameters:
     ///   - amount: The insulin amount to be delivered
     func sendBolusRequest(_ amount: Decimal) {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+            WatchLogger.shared.log("⌚️ Bolus request aborted: session unreachable")
+            return
+        }
+        
         isBolusCanceled = false // Reset canceled state when starting new bolus
         activeBolusAmount = Double(truncating: amount as NSNumber) // Set active bolus amount
 
+        WatchLogger.shared.log("⌚️ Sending bolus request: \(amount)U")
+                WatchLogger.shared.log("⌚️ isBolusCanceled = false, activeBolusAmount = \(activeBolusAmount)")
+        
         let message: [String: Any] = [
             WatchMessageKeys.bolus: amount
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("Error sending bolus request: \(error.localizedDescription)")
+            WatchLogger.shared.log("Error sending bolus request: \(error.localizedDescription)")
         }
 
         // Display pending communication animation
         showCommsAnimation = true
+        WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a carbohydrate entry request to the paired iPhone
@@ -29,7 +37,12 @@ extension WatchState {
     ///   - amount: The amount of carbs in grams
     ///   - date: The timestamp for the carb entry (defaults to current time)
     func sendCarbsRequest(_ amount: Int, _ date: Date = Date()) {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Carbs request aborted: session unreachable")
+                    return
+                }
+        
+        WatchLogger.shared.log("⌚️ Sending carbs request: \(amount)g at \(date)")
 
         let message: [String: Any] = [
             WatchMessageKeys.carbs: amount,
@@ -37,104 +50,141 @@ extension WatchState {
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("Error sending carbs request: \(error.localizedDescription)")
+            WatchLogger.shared.log("Error sending carbs request: \(error.localizedDescription)")
         }
 
         // Display pending communication animation
-        showCommsAnimation = true
+                WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a request to cancel the current override preset to the paired iPhone
     func sendCancelOverrideRequest() {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Cancel override request aborted: session unreachable")
+                    return
+                }
+
+                WatchLogger.shared.log("⌚️ Sending cancel override request")
 
         let message: [String: Any] = [
             WatchMessageKeys.cancelOverride: true
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("⌚️ Error sending cancel override request: \(error.localizedDescription)")
+            WatchLogger.shared.log("⌚️ Error sending cancel override request: \(error.localizedDescription)")
         }
 
         // Display pending communication animation
         showCommsAnimation = true
+        WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a request to activate an override preset to the paired iPhone
     /// - Parameter presetName: The name of the override preset to activate
     func sendActivateOverrideRequest(presetName: String) {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Activate override request aborted: session unreachable")
+                    return
+                }
+
+                WatchLogger.shared.log("⌚️ Sending activate override request for preset: \(presetName)")
 
         let message: [String: Any] = [
             WatchMessageKeys.activateOverride: presetName
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("⌚️ Error sending activate override request: \(error.localizedDescription)")
+            WatchLogger.shared.log("⌚️ Error sending activate override request: \(error.localizedDescription)")
         }
 
         // Display pending communication animation
         showCommsAnimation = true
+        WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a request to cancel the current temporary target to the paired iPhone
     func sendCancelTempTargetRequest() {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Cancel temp target request aborted: session unreachable")
+                    return
+                }
+
+                WatchLogger.shared.log("⌚️ Sending cancel temp target request")
 
         let message: [String: Any] = [
             WatchMessageKeys.cancelTempTarget: true
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("⌚️ Error sending cancel temp target request: \(error.localizedDescription)")
+            WatchLogger.shared.log("⌚️ Error sending cancel temp target request: \(error.localizedDescription)")
         }
 
         // Display pending communication animation
         showCommsAnimation = true
+        WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a request to activate a temporary target preset to the paired iPhone
     /// - Parameter presetName: The name of the temporary target preset to activate
     func sendActivateTempTargetRequest(presetName: String) {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Activate temp target request aborted: session unreachable")
+                    return
+                }
+
+                WatchLogger.shared.log("⌚️ Sending activate temp target request for preset: \(presetName)")
 
         let message: [String: Any] = [
             WatchMessageKeys.activateTempTarget: presetName
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("⌚️ Error sending activate temp target request: \(error.localizedDescription)")
+            WatchLogger.shared.log("⌚️ Error sending activate temp target request: \(error.localizedDescription)")
         }
 
         // Display pending communication animation
         showCommsAnimation = true
+        WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a request to cancel the current bolus delivery to the paired iPhone
     func sendCancelBolusRequest() {
         isBolusCanceled = true
 
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Cancel bolus request aborted: session unreachable")
+                    return
+                }
+
+                WatchLogger.shared.log("⌚️ Sending cancel bolus request. bolusCanceled = true")
+                WatchLogger.shared.log("⌚️ Resetting bolusProgress and activeBolusAmount to 0")
 
         let message: [String: Any] = [
             WatchMessageKeys.cancelBolus: true
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("Error sending cancel bolus request: \(error.localizedDescription)")
+            WatchLogger.shared.log("Error sending cancel bolus request: \(error.localizedDescription)")
         }
 
         // Reset when cancelled
         bolusProgress = 0
         activeBolusAmount = 0
+        WatchLogger.shared.log("⌚️ reset bolusProgress and activeBolusAmount to 0")
 
         // Display pending communication animation
         showCommsAnimation = true
+        WatchLogger.shared.log("⌚️ showCommsAnimation = true")
     }
 
     /// Sends a request to calculate a bolus recommendation based on the current carbs amount
     func requestBolusRecommendation() {
-        guard let session = session, session.isReachable else { return }
+        guard let session = session, session.isReachable else {
+                    WatchLogger.shared.log("⌚️ Bolus recommendation request aborted: session unreachable")
+                    return
+                }
+
+                WatchLogger.shared.log("⌚️ Requesting bolus recommendation for carbs: \(carbsAmount)")
 
         let message: [String: Any] = [
             WatchMessageKeys.requestBolusRecommendation: true,
@@ -142,29 +192,35 @@ extension WatchState {
         ]
 
         session.sendMessage(message, replyHandler: nil) { error in
-            print("Error requesting bolus recommendation: \(error.localizedDescription)")
+            WatchLogger.shared.log("Error requesting bolus recommendation: \(error.localizedDescription)")
         }
 
         showBolusCalculationProgress = true
+        WatchLogger.shared.log("⌚️ showBolusCalculationProgress = true")
     }
 
     func requestWatchStateUpdate() {
-        guard let session = session, session.activationState == .activated else {
-            print("⌚️ Session not activated, activating...")
-            session?.activate()
-            return
-        }
+        guard let session = session else {
+                    WatchLogger.shared.log("⌚️ No session available for state update")
+                    return
+                }
+
+                guard session.activationState == .activated else {
+                    WatchLogger.shared.log("⌚️ Session not activated. Activating...")
+                    session.activate()
+                    return
+                }
 
         if session.isReachable {
-            print("⌚️ Request an update for watch state from Trio iPhone app...")
+                    WatchLogger.shared.log("⌚️ Requesting WatchState update from iPhone")
 
-            let message = [WatchMessageKeys.requestWatchUpdate: WatchMessageKeys.watchState]
+                    let message = [WatchMessageKeys.requestWatchUpdate: WatchMessageKeys.watchState]
 
-            session.sendMessage(message, replyHandler: nil) { error in
-                print("⌚️ Update request for fresh watch state data: \(error.localizedDescription)")
-            }
-        } else {
-            print("⌚️ Phone not reachable for watch state update")
-        }
+                    session.sendMessage(message, replyHandler: nil) { error in
+                        WatchLogger.shared.log("⌚️ Error requesting WatchState update: \(error.localizedDescription)")
+                    }
+                } else {
+                    WatchLogger.shared.log("⌚️ Phone not reachable for WatchState update")
+                }
     }
 }

+ 18 - 104
Trio Watch App Extension/WatchState.swift

@@ -96,6 +96,7 @@ import WatchConnectivity
             session.delegate = self
             session.activate()
             self.session = session
+            WatchLogger.shared.log("⌚️ WCSession setup complete.")
         } else {
             WatchLogger.shared.log("⌚️ WCSession is not supported on this device")
         }
@@ -104,6 +105,8 @@ import WatchConnectivity
     // MARK: – Handle Acknowledgement Messages FROM Phone
 
     func handleAcknowledgment(success: Bool, message: String, isFinal: Bool = true) {
+        WatchLogger.shared.log("Handling acknowledgment: \(message), success: \(success), isFinal: \(isFinal)")
+
         if success {
             WatchLogger.shared.log("⌚️ Acknowledgment received: \(message)")
             acknowledgementStatus = .success
@@ -122,6 +125,7 @@ import WatchConnectivity
             DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                 self.showAcknowledgmentBanner = false
                 self.showSyncingAnimation = false // Just ensure this is 100% set to false
+                WatchLogger.shared.log("Cleared ack banner and syncing animation")
             }
         }
     }
@@ -247,109 +251,6 @@ import WatchConnectivity
         }
     }
 
-    /// Handles incoming messages from the paired iPhone when Phone is in the background
-//    func session(_: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) {
-//        WatchLogger.shared.log("⌚️ Watch received data: \(userInfo)")
-//
-//        if let stateDict = userInfo[WatchMessageKeys.watchState] as? [String: Any] {
-//                WatchLogger.shared.log("📥 Found WatchState in userInfo")
-//
-//                if let snapshot = WatchStateSnapshot(from: stateDict) {
-//                    WatchLogger.shared.log("📥 Parsed snapshot: \(snapshot.date)")
-//
-//                    Task {
-//                        await WatchStateModel.shared.handleIncomingSnapshot(snapshot)
-//                    }
-//                } else {
-//                    WatchLogger.shared.log("❌ Failed to parse WatchState snapshot from userInfo")
-//                }
-//            }
-//        // If the message has a nested "watchState" dictionary with date as TimeInterval
-//        if let watchStateDict = userInfo[WatchMessageKeys.watchState] as? [String: Any],
-//           let timestamp = watchStateDict[WatchMessageKeys.date] as? TimeInterval
-//        {
-//            let date = Date(timeIntervalSince1970: timestamp)
-//
-//            // Check if it's not older than 15 min
-//            if date >= Date().addingTimeInterval(-15 * 60) {
-//                WatchLogger.shared.log("⌚️ Handling watchState from \(date)")
-//                processWatchMessage(userInfo)
-//            } else {
-//                WatchLogger.shared.log("⌚️ Received outdated watchState data (\(date))")
-//                DispatchQueue.main.async {
-//                    self.showSyncingAnimation = false
-//                }
-//            }
-//            return
-//        }
-//
-//        // Else if the message is an "ack" at the top level
-//        // e.g. { "acknowledged": true, "message": "Started Temp Target...", "date": Date(...) }
-//        else if
-//            let acknowledged = userInfo[WatchMessageKeys.acknowledged] as? Bool,
-//            let ackMessage = userInfo[WatchMessageKeys.message] as? String
-//        {
-//            WatchLogger.shared.log("⌚️ Handling ack with message: \(ackMessage), success: \(acknowledged)")
-//            DispatchQueue.main.async {
-//                // For ack messages, we do NOT show “Syncing...”
-//                self.showSyncingAnimation = false
-//            }
-//            processWatchMessage(userInfo)
-//            return
-//
-//                    // Recommended bolus is also not part of the WatchState message, hence the extra condition here
-//        } else if
-//            let recommendedBolus = userInfo[WatchMessageKeys.recommendedBolus] as? NSNumber
-//        {
-//            WatchLogger.shared.log("⌚️ Received recommended bolus: \(recommendedBolus)")
-//            self.recommendedBolus = recommendedBolus.decimalValue
-//            showBolusCalculationProgress = false
-//            return
-//
-//                    // Handle bolus progress updates
-//        } else if
-//            let timestamp = userInfo[WatchMessageKeys.bolusProgressTimestamp] as? TimeInterval,
-//            let progress = userInfo[WatchMessageKeys.bolusProgress] as? Double,
-//            let activeBolusAmount = userInfo[WatchMessageKeys.activeBolusAmount] as? Double,
-//            let deliveredAmount = userInfo[WatchMessageKeys.deliveredAmount] as? Double
-//        {
-//            let date = Date(timeIntervalSince1970: timestamp)
-//
-//            // Check if it's not older than 5 min
-//            if date >= Date().addingTimeInterval(-5 * 60) {
-//                WatchLogger.shared.log("⌚️ Handling bolusProgress (sent at \(date))")
-//                DispatchQueue.main.async {
-//                    if !self.isBolusCanceled {
-//                        self.bolusProgress = progress
-//                        self.activeBolusAmount = activeBolusAmount
-//                        self.deliveredAmount = deliveredAmount
-//                    }
-//                }
-//            } else {
-//                WatchLogger.shared.log("⌚️ Received outdated bolus progress (sent at \(date))")
-//                DispatchQueue.main.async {
-//                    self.bolusProgress = 0
-//                    self.activeBolusAmount = 0
-//                }
-//            }
-//            return
-//
-//                    // Handle bolus cancellation
-//        } else if
-//            userInfo[WatchMessageKeys.bolusCanceled] as? Bool == true
-//        {
-//            DispatchQueue.main.async {
-//                self.bolusProgress = 0
-//                self.activeBolusAmount = 0
-//            }
-//            return
-//        } else {
-//            WatchLogger.shared.log("⌚️ Faulty data. Skipping...")
-//            DispatchQueue.main.async {
-//                self.showSyncingAnimation = false
-//            }
-//        }
-//    }
     func session(_: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) {
         guard let snapshot = WatchStateSnapshot(from: userInfo) else {
             print("⌚️ Invalid snapshot received")
@@ -407,6 +308,8 @@ 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 = lastWatchStateUpdate else {
+            WatchLogger.shared.log("Forcing initial WatchState update")
+
             // If there's no recorded timestamp, we must force a fresh update immediately.
             showSyncingAnimation = true
             requestWatchStateUpdate()
@@ -415,6 +318,7 @@ import WatchConnectivity
 
         let now = Date().timeIntervalSince1970
         let secondsSinceUpdate = now - lastUpdateTimestamp
+        WatchLogger.shared.log("Time since last update: \(secondsSinceUpdate) seconds")
 
         // If more than 15 seconds have elapsed since the last update, force an(other) update.
         if secondsSinceUpdate > 15 {
@@ -470,7 +374,7 @@ import WatchConnectivity
            let lastTimestamp = lastWatchStateUpdate,
            incomingTimestamp <= lastTimestamp
         {
-            WatchLogger.shared.log("⚠️ Skipping UI update — outdated WatchState (\(incomingTimestamp))")
+            WatchLogger.shared.log("Skipping UI update — outdated WatchState (\(incomingTimestamp))")
             return
         }
 
@@ -479,6 +383,8 @@ import WatchConnectivity
             self.showSyncingAnimation = true
         }
 
+        WatchLogger.shared.log("Merging new WatchState data with keys: \(newData.keys.joined(separator: ", "))")
+
         // 2) Merge data into our pendingData
         pendingData.merge(newData) { _, newVal in newVal }
 
@@ -487,6 +393,7 @@ import WatchConnectivity
 
         // 4) Create and schedule a new finalization
         let workItem = DispatchWorkItem { [self] in
+            WatchLogger.shared.log("⏳ Debounced update fired")
             self.finalizePendingData()
         }
         finalizeWorkItem = workItem
@@ -496,6 +403,8 @@ import WatchConnectivity
     /// Applies all pending data to the watch state in one shot
     private func finalizePendingData() {
         guard !pendingData.isEmpty else {
+            WatchLogger.shared.log("⚠️ finalizePendingData called with empty data")
+
             // If we have no actual data, just end syncing
             DispatchQueue.main.async {
                 self.showSyncingAnimation = false
@@ -515,12 +424,17 @@ import WatchConnectivity
         DispatchQueue.main.async {
             self.showSyncingAnimation = false
         }
+
+        WatchLogger.shared.log("✅ Watch UI update complete")
     }
 
     /// Updates the UI properties
     private func processRawDataForWatchState(_ message: [String: Any]) {
+        WatchLogger.shared.log("Processing raw WatchState data with keys: \(message.keys.joined(separator: ", "))")
+
         if let timestamp = message[WatchMessageKeys.date] as? TimeInterval {
             lastWatchStateUpdate = timestamp
+            WatchLogger.shared.log("Updated lastWatchStateUpdate: \(timestamp)")
         }
 
         if let currentGlucose = message[WatchMessageKeys.currentGlucose] as? String {