AlarmTask.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //
  2. // AlarmTask.swift
  3. // LoopFollow
  4. //
  5. // Created by Jonas Björkert on 2025-01-12.
  6. // Copyright © 2025 Jon Fawcett. All rights reserved.
  7. //
  8. import Foundation
  9. extension MainViewController {
  10. func scheduleAlarmTask(initialDelay: TimeInterval = 30) {
  11. let firstRun = Date().addingTimeInterval(initialDelay)
  12. TaskScheduler.shared.scheduleTask(id: .alarmCheck, nextRun: firstRun) { [weak self] in
  13. guard let self = self else { return }
  14. self.alarmTaskAction()
  15. }
  16. }
  17. func alarmTaskAction() {
  18. DispatchQueue.main.async {
  19. let latestOverrideStart = self.overrideGraphData.last?.date
  20. let latestOverrideEnd = self.overrideGraphData.last?.endDate
  21. let latestTempTargetStart = self.tempTargetGraphData.last?.date
  22. let latestTempTargetEnd = self.tempTargetGraphData.last?.endDate
  23. let recBolus = UserDefaultsRepository.deviceRecBolus.value
  24. let COB = self.latestCOB?.value
  25. let alarmData = AlarmData(
  26. bgReadings: self.bgData
  27. .suffix(24)
  28. .map { GlucoseValue(sgv: $0.sgv, date: Date(timeIntervalSince1970: $0.date)) }, /// These are oldest .. newest
  29. predictionData: self.predictionData
  30. .prefix(12)
  31. .map { GlucoseValue(sgv: $0.sgv, date: Date(timeIntervalSince1970: $0.date)) }, /// These are oldest .. newest, Predictions not currently available for Trio
  32. expireDate: Storage.shared.expirationDate.value,
  33. lastLoopTime: UserDefaultsRepository.alertLastLoopTime.value,
  34. latestOverrideStart: latestOverrideStart,
  35. latestOverrideEnd: latestOverrideEnd,
  36. latestTempTargetStart: latestTempTargetStart,
  37. latestTempTargetEnd: latestTempTargetEnd,
  38. recBolus: recBolus,
  39. COB: COB
  40. )
  41. let finalAlarmData: AlarmData
  42. if Observable.shared.debug.value {
  43. self.saveLatestAlarmDataToFile(alarmData)
  44. finalAlarmData = self.loadTestAlarmData() ?? alarmData
  45. } else {
  46. finalAlarmData = alarmData
  47. }
  48. LogManager.shared.log(category: .alarm, message: "Checking alarms based on \(finalAlarmData)", isDebug: true)
  49. AlarmManager.shared.checkAlarms(data: finalAlarmData)
  50. TaskScheduler.shared.rescheduleTask(id: .alarmCheck, to: Date().addingTimeInterval(60))
  51. }
  52. }
  53. func saveLatestAlarmDataToFile(_ alarmData: AlarmData) {
  54. let encoder = JSONEncoder()
  55. encoder.dateEncodingStrategy = .iso8601
  56. do {
  57. let data = try encoder.encode(alarmData)
  58. let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("latestAlarmData.json")
  59. try data.write(to: url)
  60. } catch {
  61. LogManager.shared.log(category: .alarm, message: "Failed to save latest AlarmData: \(error)", isDebug: true)
  62. }
  63. }
  64. func loadTestAlarmData() -> AlarmData? {
  65. let fileManager = FileManager.default
  66. let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("testAlarmData.json")
  67. if fileManager.fileExists(atPath: url.path) {
  68. do {
  69. let data = try Data(contentsOf: url)
  70. let decoder = JSONDecoder()
  71. decoder.dateDecodingStrategy = .iso8601
  72. let alarmData = try decoder.decode(AlarmData.self, from: data)
  73. LogManager.shared.log(category: .alarm, message: "Loaded test AlarmData from \(url.path)", isDebug: true)
  74. return alarmData
  75. } catch {
  76. LogManager.shared.log(category: .alarm, message: "Failed to load test AlarmData: \(error)", isDebug: true)
  77. }
  78. }
  79. return nil
  80. }
  81. }