AlarmTask.swift 4.2 KB

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