فهرست منبع

re-add docstrings

add docstrings back into GarminManager
Robert 4 ماه پیش
والد
کامیت
1aed6f442d
2فایلهای تغییر یافته به همراه96 افزوده شده و 1 حذف شده
  1. 22 0
      Trio/Sources/Models/GarminWatchState.swift
  2. 74 1
      Trio/Sources/Services/WatchManager/GarminManager.swift

+ 22 - 0
Trio/Sources/Models/GarminWatchState.swift

@@ -15,16 +15,38 @@ import SwiftUI
 struct GarminWatchState: Hashable, Equatable, Sendable, Encodable {
     /// Timestamp of the glucose reading in milliseconds since Unix epoch
     var date: UInt64?
+
+    /// Sensor glucose value in raw mg/dL (no unit conversion applied)
     var sgv: Int16?
+
+    /// Change in glucose since previous reading as an integer
     var delta: Int16?
+
+    /// Glucose trend direction (e.g., "Flat", "FortyFiveUp", "SingleUp")
     var direction: String?
+
+    /// Signal noise level (optional, typically not used)
     var noise: Double?
+
+    /// Unit hint for the watchface ("mgdl" or "mmol")
     var units_hint: String?
+
+    /// Insulin on board as a decimal value (only in first array entry)
     var iob: Double?
+
+    /// Current temp basal rate in U/hr (only in first array entry)
     var tbr: Double?
+
+    /// Carbs on board as a decimal value (only in first array entry)
     var cob: Double?
+
+    /// Predicted eventual blood glucose (excluded if data type 2 is set to TBR)
     var eventualBG: Int16?
+
+    /// Current insulin sensitivity factor as an integer (only in first array entry)
     var isf: Int16?
+
+    /// AutoISF sensitivity ratio (included only if data type 1 is set to sensRatio)
     var sensRatio: Double?
 
     // MARK: - Display Configuration Fields

+ 74 - 1
Trio/Sources/Services/WatchManager/GarminManager.swift

@@ -35,26 +35,48 @@ protocol GarminManager {
 final class BaseGarminManager: NSObject, GarminManager, Injectable {
     // MARK: - Dependencies & Properties
 
+    /// Observes system-wide notifications, including `.openFromGarminConnect`.
     @Injected() private var notificationCenter: NotificationCenter!
+
+    /// Broadcaster used for publishing or subscribing to global events (e.g., unit changes).
     @Injected() private var broadcaster: Broadcaster!
+
+    /// APSManager containing insulin pump logic, e.g., for making bolus requests, reading basal info, etc.
     @Injected() private var apsManager: APSManager!
+
+    /// Manages local user settings, such as glucose units (mg/dL or mmol/L).
     @Injected() private var settingsManager: SettingsManager!
+
+    /// Stores, retrieves, and updates glucose data in CoreData.
     @Injected() private var glucoseStorage: GlucoseStorage!
+
+    /// Stores, retrieves, and updates insulin dose determinations in CoreData.
     @Injected() private var determinationStorage: DeterminationStorage!
+
     @Injected() private var iobService: IOBService!
 
+    /// Persists the user's device list between app launches.
     @Persisted(key: "BaseGarminManager.persistedDevices") private var persistedDevices: [GarminDevice] = []
 
+    /// Router for presenting alerts or navigation flows (injected via Swinject).
     private let router: Router
+
+    /// Garmin ConnectIQ shared instance for watch interactions.
     private let connectIQ = ConnectIQ.sharedInstance()
+
+    /// Keeps references to watch apps (both watchface & data field) for each registered device.
     private var watchApps: [IQApp] = []
+
+    /// A set of Combine cancellables for managing the lifecycle of various subscriptions.
     private var cancellables = Set<AnyCancellable>()
+
+    /// Holds a promise used when the user is selecting devices (via `showDeviceSelection()`).
     private var deviceSelectionPromise: Future<[IQDevice], Never>.Promise?
 
     /// Subject for debouncing watch state updates
     private let watchStateSubject = PassthroughSubject<Data, Never>()
 
-    /// Current glucose units
+    /// Current glucose units, either mg/dL or mmol/L, read from user settings.
     private var units: GlucoseUnits = .mgdL
 
     // MARK: - Debug Logging
@@ -95,22 +117,34 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
     /// Queue for handling Core Data change notifications
     private let queue = DispatchQueue(label: "BaseGarminManager.queue", qos: .utility)
 
+    /// Publishes any changed CoreData objects that match our filters (e.g., OrefDetermination, GlucoseStored).
     private var coreDataPublisher: AnyPublisher<Set<NSManagedObjectID>, Never>?
+
+    /// Additional local subscriptions (separate from `cancellables`) for CoreData events.
     private var subscriptions = Set<AnyCancellable>()
 
+    /// Represents the context for background tasks in CoreData.
     let backgroundContext = CoreDataStack.shared.newTaskContext()
+
+    /// Represents the main (view) context for CoreData, typically used on the main thread.
     let viewContext = CoreDataStack.shared.persistentContainer.viewContext
 
     /// Array of Garmin `IQDevice` objects currently tracked.
+    /// Changing this property triggers re-registration and updates persisted devices.
     private(set) var devices: [IQDevice] = [] {
         didSet {
+            // Persist newly updated device list
             persistedDevices = devices.map(GarminDevice.init)
+            // Re-register for events, app messages, etc.
             registerDevices(devices)
         }
     }
 
     // MARK: - Initialization
 
+    /// Creates a new `BaseGarminManager`, injecting required services, restoring any persisted devices,
+    /// and setting up watchers for data changes (e.g., glucose updates).
+    /// - Parameter resolver: Swinject resolver for injecting dependencies like the Router.
     init(resolver: Resolver) {
         router = resolver.resolve(Router.self)!
         super.init()
@@ -188,6 +222,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 
     // MARK: - Internal Setup / Handlers
 
+    /// Sets up handlers for OrefDetermination and GlucoseStored entity changes in CoreData.
+    /// When these change, we re-compute the Garmin watch state and send updates to the watch.
     private func registerHandlers() {
         // OrefDetermination changes - debounce at CoreData level
         coreDataPublisher?
@@ -262,6 +298,9 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 
     // MARK: - CoreData Fetch Methods
 
+    /// Fetches recent glucose readings from CoreData, up to specified limit.
+    /// - Parameter limit: Maximum number of glucose entries to fetch (default: 2)
+    /// - Returns: An array of `NSManagedObjectID`s for glucose readings.
     private func fetchGlucose(limit: Int = 2) async throws -> [NSManagedObjectID] {
         let results = try await CoreDataStack.shared.fetchEntitiesAsync(
             ofType: GlucoseStored.self,
@@ -482,6 +521,9 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 
     // MARK: - Device & App Registration
 
+    /// Registers the given devices for ConnectIQ events (device status changes) and watch app messages.
+    /// It also creates and registers watch apps (watchface + data field) for each device.
+    /// - Parameter devices: The devices to register.
     private func registerDevices(_ devices: [IQDevice]) {
         watchApps.removeAll()
 
@@ -511,6 +553,7 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
         }
     }
 
+    /// Restores previously persisted devices from local storage into `devices`.
     private func restoreDevices() {
         devices = persistedDevices.map(\.iqDevice)
     }
@@ -557,6 +600,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 
     // MARK: - Combine Subscriptions
 
+    /// Subscribes to the `.openFromGarminConnect` notification, parsing devices from the given URL
+    /// and updating the device list accordingly.
     private func subscribeToOpenFromGarminConnect() {
         notificationCenter
             .publisher(for: .openFromGarminConnect)
@@ -579,6 +624,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 
     // MARK: - Parsing & Broadcasting
 
+    /// Parses devices from a Garmin Connect URL and updates our `devices` property.
+    /// - Parameter url: The URL provided by Garmin Connect containing device selection info.
     private func parseDevices(for url: URL) {
         let parsed = connectIQ?.parseDeviceSelectionResponse(from: url) as? [IQDevice]
         devices = parsed ?? []
@@ -636,6 +683,9 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 
     // MARK: - GarminManager Conformance
 
+    /// Prompts the user to select one or more Garmin devices, returning a publisher that emits
+    /// the final array of selected devices once the user finishes selection.
+    /// - Returns: An `AnyPublisher` emitting `[IQDevice]` on success, or empty array on error/timeout.
     func selectDevices() -> AnyPublisher<[IQDevice], Never> {
         Future { [weak self] promise in
             guard let self = self else {
@@ -650,16 +700,25 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
         .eraseToAnyPublisher()
     }
 
+    /// Updates the manager's list of devices, typically after user selection or manual changes.
+    /// - Parameter devices: The new array of `IQDevice` objects to track.
     func updateDeviceList(_ devices: [IQDevice]) {
         self.devices = devices
     }
 
+    /// Sends the given watch state data to the debounce subject for eventual broadcast.
+    /// - Parameter data: JSON-encoded data representing the latest watch state.
     func sendWatchStateData(_ data: Data) {
         watchStateSubject.send(data)
     }
 
     // MARK: - Helper: Sending Messages
 
+    /// Sends a message to a given IQApp with optional progress and completion callbacks.
+    /// - Parameters:
+    ///   - msg: The data to send to the watch app.
+    ///   - app: The `IQApp` instance representing the watchface or data field.
+    ///   - appName: The display name of the app for logging.
     private func sendMessage(_ msg: Any, to app: IQApp, appName: String) {
         connectIQ?.sendMessage(
             msg,
@@ -682,6 +741,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable {
 extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppMessageDelegate {
     // MARK: - IQUIOverrideDelegate
 
+    /// Called if the Garmin Connect Mobile app is not installed or otherwise not available.
+    /// Typically, you would show an alert or prompt the user to install the app from the store.
     func needsToInstallConnectMobile() {
         debug(.apsManager, "Garmin is not available")
         let messageCont = MessageContent(
@@ -695,6 +756,10 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
 
     // MARK: - IQDeviceEventDelegate
 
+    /// Called whenever the status of a registered Garmin device changes (e.g., connected, not found, etc.).
+    /// - Parameters:
+    ///   - device: The device whose status has changed.
+    ///   - status: The new status for the device.
     func deviceStatusChanged(_: IQDevice, status: IQDeviceStatus) {
         // Always log connection state changes - critical for diagnosing SDK issues
         switch status {
@@ -715,6 +780,12 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
 
     // MARK: - IQAppMessageDelegate
 
+    /// Called when a message arrives from a Garmin watch app (watchface or data field).
+    /// If the watch requests a "status" update, we call `setupGarminWatchState()` asynchronously
+    /// and re-send the watch state data.
+    /// - Parameters:
+    ///   - message: The message content from the watch app.
+    ///   - app: The watch app sending the message.
     func receivedMessage(_ message: Any, from app: IQApp) {
         let appName = appDisplayName(for: app.uuid!)
         debugGarmin("Garmin: Received message '\(message)' from \(appName)")
@@ -737,6 +808,8 @@ extension BaseGarminManager: IQUIOverrideDelegate, IQDeviceEventDelegate, IQAppM
 }
 
 extension BaseGarminManager: SettingsObserver {
+    /// Called whenever TrioSettings changes (e.g., user toggles mg/dL vs. mmol/L).
+    /// - Parameter _: The updated TrioSettings instance.
     func settingsDidChange(_: TrioSettings) {
         units = settingsManager.settings.units