AlarmTask.swift 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // LoopFollow
  2. // AlarmTask.swift
  3. import Foundation
  4. extension MainViewController {
  5. func scheduleAlarmTask(initialDelay: TimeInterval = 30) {
  6. let firstRun = Date().addingTimeInterval(initialDelay)
  7. TaskScheduler.shared.scheduleTask(id: .alarmCheck, nextRun: firstRun) { [weak self] in
  8. guard let self = self else { return }
  9. self.alarmTaskAction()
  10. }
  11. }
  12. func alarmTaskAction() {
  13. DispatchQueue.main.async {
  14. let now = Date().timeIntervalSince1970
  15. let latestOverrideStart = self.overrideGraphData.last { $0.date <= now }?.date
  16. let latestOverrideEnd = self.overrideGraphData.last { $0.endDate <= now }?.endDate
  17. let latestTempTargetStart = self.tempTargetGraphData.last { $0.date <= now }?.date
  18. let latestTempTargetEnd = self.tempTargetGraphData.last { $0.endDate <= now }?.endDate
  19. let recBolus = Observable.shared.deviceRecBolus.value
  20. let COB = self.latestCOB?.value
  21. let sensorInsertedAt = Storage.shared.sageInsertTime.value
  22. let pumpInsertTime = Storage.shared.cageInsertTime.value
  23. let latestPumpVol = self.latestPumpVolume
  24. let bolusEntries = self.bolusData.map { BolusEntry(units: $0.value, date: Date(timeIntervalSince1970: $0.date)) }
  25. let latestBattery = Observable.shared.deviceBatteryLevel.value
  26. let latestPumpBattery = Observable.shared.pumpBatteryLevel.value
  27. let recentCarbs: [CarbSample] = self.carbData.map { CarbSample(grams: $0.value, date: Date(timeIntervalSince1970: $0.date)) }
  28. let alarmData = AlarmData(
  29. bgReadings: self.bgData
  30. .suffix(24)
  31. .map { GlucoseValue(sgv: $0.sgv, date: Date(timeIntervalSince1970: $0.date)) }, /// These are oldest .. newest
  32. predictionData: self.predictionData
  33. .prefix(12)
  34. .map { GlucoseValue(sgv: $0.sgv, date: Date(timeIntervalSince1970: $0.date)) }, /// These are oldest .. newest, Predictions not currently available for Trio
  35. expireDate: Storage.shared.expirationDate.value,
  36. lastLoopTime: Observable.shared.alertLastLoopTime.value,
  37. latestOverrideStart: latestOverrideStart,
  38. latestOverrideEnd: latestOverrideEnd,
  39. latestTempTargetStart: latestTempTargetStart,
  40. latestTempTargetEnd: latestTempTargetEnd,
  41. recBolus: recBolus,
  42. COB: COB,
  43. sageInsertTime: sensorInsertedAt,
  44. pumpInsertTime: pumpInsertTime,
  45. latestPumpVolume: latestPumpVol,
  46. IOB: self.latestIOB?.value,
  47. recentBoluses: bolusEntries,
  48. latestBattery: latestBattery,
  49. latestBatteryIsCharging: Observable.shared.deviceBatteryIsCharging.value,
  50. latestPumpBattery: latestPumpBattery,
  51. batteryHistory: self.deviceBatteryData,
  52. recentCarbs: recentCarbs,
  53. dbSizePercentage: Observable.shared.dbSizePercentage.value
  54. )
  55. let finalAlarmData: AlarmData
  56. if Observable.shared.debug.value {
  57. self.saveLatestAlarmDataToFile(alarmData)
  58. finalAlarmData = self.loadTestAlarmData() ?? alarmData
  59. } else {
  60. finalAlarmData = alarmData
  61. }
  62. LogManager.shared.log(category: .alarm, message: "Checking alarms based on \(finalAlarmData)", isDebug: true)
  63. LogManager.shared.log(category: .alarm, message: "Alarms \(Storage.shared.alarms.value)", isDebug: true)
  64. AlarmManager.shared.checkAlarms(data: finalAlarmData)
  65. TaskScheduler.shared.rescheduleTask(id: .alarmCheck, to: Date().addingTimeInterval(60))
  66. }
  67. }
  68. func saveLatestAlarmDataToFile(_ alarmData: AlarmData) {
  69. let encoder = JSONEncoder()
  70. encoder.dateEncodingStrategy = .iso8601
  71. do {
  72. let data = try encoder.encode(alarmData)
  73. let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("latestAlarmData.json")
  74. try data.write(to: url)
  75. } catch {
  76. LogManager.shared.log(category: .alarm, message: "Failed to save latest AlarmData: \(error)", isDebug: true)
  77. }
  78. }
  79. func loadTestAlarmData() -> AlarmData? {
  80. let fileManager = FileManager.default
  81. let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("testAlarmData.json")
  82. if fileManager.fileExists(atPath: url.path) {
  83. do {
  84. let data = try Data(contentsOf: url)
  85. let decoder = JSONDecoder()
  86. decoder.dateDecodingStrategy = .iso8601
  87. let alarmData = try decoder.decode(AlarmData.self, from: data)
  88. LogManager.shared.log(category: .alarm, message: "Loaded test AlarmData from \(url.path)", isDebug: true)
  89. return alarmData
  90. } catch {
  91. LogManager.shared.log(category: .alarm, message: "Failed to load test AlarmData: \(error)", isDebug: true)
  92. }
  93. }
  94. return nil
  95. }
  96. }