Jonas Björkert 1 год назад
Родитель
Сommit
cdff6db7d9

+ 1 - 1
LoopFollow/Controllers/Nightscout/DeviceStatus.swift

@@ -109,7 +109,7 @@ extension MainViewController {
                         batteryText = String(format: "%.0f", upbat) + "%"
                     }
                     infoManager.updateInfoData(type: .battery, value: batteryText)
-                    UserDefaultsRepository.deviceBatteryLevel.value = upbat
+                    Observable.shared.deviceBatteryLevel.value = upbat
 
                     let timestamp = uploader["timestamp"] as? Date ?? Date()
                     let currentBattery = DataStructs.batteryStruct(batteryLevel: upbat, timestamp: timestamp)

+ 1 - 1
LoopFollow/Controllers/Nightscout/DeviceStatusLoop.swift

@@ -101,7 +101,7 @@ extension MainViewController {
                 if let recBolus = lastLoopRecord["recommendedBolus"] as? Double {
                     let formattedRecBolus = String(format: "%.2fU", recBolus)
                     infoManager.updateInfoData(type: .recBolus, value: formattedRecBolus)
-                    UserDefaultsRepository.deviceRecBolus.value = recBolus
+                    Observable.shared.deviceRecBolus.value = recBolus
                 }
                 if let loopStatus = lastLoopRecord["recommendedTempBasal"] as? [String: AnyObject] {
                     if let tempBasalTime = formatter.date(from: (loopStatus["timestamp"] as! String))?.timeIntervalSince1970 {

+ 2 - 2
LoopFollow/Controllers/Nightscout/DeviceStatusOpenAPS.swift

@@ -120,9 +120,9 @@ extension MainViewController {
             // Insulin Required
             if let insulinReqMetric = InsulinMetric(from: enactedOrSuggested, key: "insulinReq") {
                 infoManager.updateInfoData(type: .recBolus, value: insulinReqMetric)
-                UserDefaultsRepository.deviceRecBolus.value = insulinReqMetric.value
+                Observable.shared.deviceRecBolus.value = insulinReqMetric.value
             } else {
-                UserDefaultsRepository.deviceRecBolus.value = 0
+                Observable.shared.deviceRecBolus.value = 0
             }
 
             // Autosens

+ 2 - 0
LoopFollow/Storage/Observable.swift

@@ -31,6 +31,8 @@ class Observable {
     var chartSettingsChanged = ObservableValue<Bool>(default: false)
 
     var alertLastLoopTime = ObservableValue<TimeInterval?>(default: nil)
+    var deviceRecBolus = ObservableValue<Double?>(default: nil)
+    var deviceBatteryLevel = ObservableValue<Double?>(default: nil)
 
     private init() {}
 }

+ 77 - 3
LoopFollow/Storage/Storage+Migrate.swift

@@ -302,6 +302,9 @@ extension Storage {
         migratePumpVolumeAlarm()
         migrateIOBAlarm()
         migrateCOBAlarm()
+        migrateBatteryAlarm()
+        migrateBatteryDropAlarm()
+        migrateRecBolusAlarm()
     }
 
     // MARK: - One-off alarm migrations
@@ -1518,9 +1521,80 @@ extension Storage {
         Storage.shared.alarms.value.append(alarm)
     }
 
-    // -----------------------------------------------------------------------------
+    // =============================================================================
+    //  BATTERY-LEVEL alarm  (old keys → .battery)
+    // =============================================================================
+    private func migrateBatteryAlarm() {
+        guard UserDefaultsValue<Bool>(key: "alertBatteryActive",
+                                      default: false).exists else { return }
 
-    // MARK: - Inject into main migrate() entry point
+        var alarm = Alarm(type: .battery)
+        alarm.name = "Low Battery"
+        alarm.isEnabled = take("alertBatteryActive", false)
+        alarm.threshold = Double(take("alertBatteryLevel", 25)) // %
+        alarm.snoozeDuration = take("alertBatterySnoozeHours", 1) * 60
+        alarm.snoozedUntil = take("alertBatterySnoozedTime", nil as Date?)
+        alarm.soundFile = SoundFile(rawValue:
+            take("alertBatterySound", "Machine_Charge"))
+            ?? .machineCharge
 
-    // -----------------------------------------------------------------------------
+        // ── audio – legacy had a simple Bool “repeat / no-repeat”
+        let rpt = take("alertBatteryRepeat", true)
+        alarm.playSoundOption = .always // no day/night picker in legacy UI
+        alarm.repeatSoundOption = rpt ? .always : .never
+
+        alarm.activeOption = .always // no day/night activation picker
+        Storage.shared.alarms.value.append(alarm)
+    }
+
+    // =============================================================================
+    //  BATTERY-DROP alarm  (old keys → .batteryDrop)
+    // =============================================================================
+    private func migrateBatteryDropAlarm() {
+        guard UserDefaultsValue<Bool>(key: "alertBatteryDropActive",
+                                      default: false).exists else { return }
+
+        var alarm = Alarm(type: .batteryDrop)
+        alarm.name = "Battery Drop"
+        alarm.isEnabled = take("alertBatteryDropActive", false)
+        alarm.delta = Double(take("alertBatteryDropPercentage", 5)) // % drop
+        alarm.monitoringWindow = take("alertBatteryDropPeriod", 15) // min
+        alarm.snoozeDuration = take("alertBatteryDropSnoozeHours", 1) * 60
+        alarm.snoozedUntil = take("alertBatteryDropSnoozedTime", nil as Date?)
+        alarm.soundFile = SoundFile(rawValue:
+            take("alertBatteryDropSound", "Machine_Charge"))
+            ?? .machineCharge
+
+        let rpt = take("alertBatteryDropRepeat", true)
+        alarm.playSoundOption = .always
+        alarm.repeatSoundOption = rpt ? .always : .never
+        alarm.activeOption = .always
+
+        Storage.shared.alarms.value.append(alarm)
+    }
+
+    // =============================================================================
+    //  REC-BOLUS alarm  (old keys → .recBolus)
+    // =============================================================================
+    private func migrateRecBolusAlarm() {
+        guard UserDefaultsValue<Bool>(key: "alertRecBolusActive",
+                                      default: false).exists else { return }
+
+        var alarm = Alarm(type: .recBolus)
+        alarm.name = "Recommended Bolus"
+        alarm.isEnabled = take("alertRecBolusActive", false)
+        alarm.delta = take("alertRecBolusLevel", 1.0) // units
+        alarm.snoozeDuration = take("alertRecBolusSnooze", 5) // min
+        alarm.snoozedUntil = take("alertRecBolusSnoozedTime", nil as Date?)
+        alarm.soundFile = SoundFile(rawValue:
+            take("alertRecBolusSound", "Dhol_Shuffleloop"))
+            ?? .dholShuffleloop
+
+        let rpt = take("alertRecBolusRepeat", false)
+        alarm.playSoundOption = .always
+        alarm.repeatSoundOption = rpt ? .always : .never
+        alarm.activeOption = .always
+
+        Storage.shared.alarms.value.append(alarm)
+    }
 }

+ 0 - 27
LoopFollow/Storage/UserDefaults.swift

@@ -97,33 +97,6 @@ class UserDefaultsRepository {
     static let alertCageInsertTime = UserDefaultsValue<TimeInterval>(key: "alertCageInsertTime", default: 0)
     static let alertSageInsertTime = UserDefaultsValue<TimeInterval>(key: "alertSageInsertTime", default: 0)
 
-    static let alertBatteryActive = UserDefaultsValue<Bool>(key: "alertBatteryActive", default: false)
-    static let alertBatteryLevel = UserDefaultsValue<Int>(key: "alertBatteryLevel", default: 25)
-    static let alertBatterySound = UserDefaultsValue<String>(key: "alertBatterySound", default: "Machine_Charge")
-    static let alertBatteryRepeat = UserDefaultsValue<Bool>(key: "alertBatteryRepeat", default: true)
-    static let alertBatteryIsSnoozed = UserDefaultsValue<Bool>(key: "alertBatteryIsSnoozed", default: false)
-    static let alertBatterySnoozedTime = UserDefaultsValue<Date?>(key: "alertBatterySnoozedTime", default: nil)
-    static let alertBatterySnoozeHours = UserDefaultsValue<Int>(key: "alertBatterySnoozeHours", default: 1)
-    static var deviceBatteryLevel: UserDefaultsValue<Double> = UserDefaultsValue(key: "deviceBatteryLevel", default: 100.0)
-
-    static let alertBatteryDropActive = UserDefaultsValue<Bool>(key: "alertBatteryDropActive", default: false)
-    static let alertBatteryDropPercentage = UserDefaultsValue<Int>(key: "alertBatteryDropPercentage", default: 5)
-    static let alertBatteryDropPeriod = UserDefaultsValue<Int>(key: "alertBatteryDropPeriod", default: 15)
-    static let alertBatteryDropSound = UserDefaultsValue<String>(key: "alertBatteryDropSound", default: "Machine_Charge")
-    static let alertBatteryDropRepeat = UserDefaultsValue<Bool>(key: "alertBatteryDropRepeat", default: true)
-    static let alertBatteryDropIsSnoozed = UserDefaultsValue<Bool>(key: "alertBatteryDropIsSnoozed", default: false)
-    static let alertBatteryDropSnoozedTime = UserDefaultsValue<Date?>(key: "alertBatteryDropSnoozedTime", default: nil)
-    static let alertBatteryDropSnoozeHours = UserDefaultsValue<Int>(key: "alertBatteryDropSnoozeHours", default: 1)
-
-    static let alertRecBolusActive = UserDefaultsValue<Bool>(key: "alertRecBolusActive", default: false)
-    static let alertRecBolusLevel = UserDefaultsValue<Double>(key: "alertRecBolusLevel", default: 1) // Unit[s]
-    static let alertRecBolusSound = UserDefaultsValue<String>(key: "alertRecBolusSound", default: "Dhol_Shuffleloop")
-    static let alertRecBolusRepeat = UserDefaultsValue<Bool>(key: "alertRecBolusRepeat", default: false)
-    static let alertRecBolusIsSnoozed = UserDefaultsValue<Bool>(key: "alertRecBolusIsSnoozed", default: false)
-    static let alertRecBolusSnooze = UserDefaultsValue<Int>(key: "alertRecBolusSnooze", default: 5)
-    static let alertRecBolusSnoozedTime = UserDefaultsValue<Date?>(key: "alertRecBolusSnoozedTime", default: nil)
-    static var deviceRecBolus: UserDefaultsValue<Double> = UserDefaultsValue(key: "deviceRecBolus", default: 0.0)
-
     // What version is the cache valid for
     static let cachedForVersion = UserDefaultsValue<String?>(key: "cachedForVersion", default: nil)
 

+ 2 - 2
LoopFollow/Task/AlarmTask.swift

@@ -20,13 +20,13 @@ extension MainViewController {
             let latestOverrideEnd = self.overrideGraphData.last { $0.endDate <= now }?.endDate
             let latestTempTargetStart = self.tempTargetGraphData.last { $0.date <= now }?.date
             let latestTempTargetEnd = self.tempTargetGraphData.last { $0.endDate <= now }?.endDate
-            let recBolus = UserDefaultsRepository.deviceRecBolus.value
+            let recBolus = Observable.shared.deviceRecBolus.value
             let COB = self.latestCOB?.value
             let sensorInsertedAt = UserDefaultsRepository.alertSageInsertTime.value
             let pumpInsertTime = UserDefaultsRepository.alertCageInsertTime.value
             let latestPumpVol = self.latestPumpVolume
             let bolusEntries = self.bolusData.map { BolusEntry(units: $0.value, date: Date(timeIntervalSince1970: $0.date)) }
-            let latestBattery = UserDefaultsRepository.deviceBatteryLevel.value
+            let latestBattery = Observable.shared.deviceBatteryLevel.value
             let recentCarbs: [CarbSample] = self.carbData.map { CarbSample(grams: $0.value, date: Date(timeIntervalSince1970: $0.date)) }
 
             let alarmData = AlarmData(