TrioRemoteControl.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import CoreData
  2. import Foundation
  3. import Swinject
  4. class TrioRemoteControl: Injectable {
  5. static let shared = TrioRemoteControl()
  6. @Injected() internal var tempTargetsStorage: TempTargetsStorage!
  7. @Injected() internal var carbsStorage: CarbsStorage!
  8. @Injected() internal var nightscoutManager: NightscoutManager!
  9. @Injected() internal var overrideStorage: OverrideStorage!
  10. @Injected() internal var settings: SettingsManager!
  11. private let timeWindow: TimeInterval = 600 // Defines how old messages that are accepted, 10 minutes
  12. internal let pumpHistoryFetchContext: NSManagedObjectContext
  13. internal let viewContext: NSManagedObjectContext
  14. private init() {
  15. pumpHistoryFetchContext = CoreDataStack.shared.newTaskContext()
  16. viewContext = CoreDataStack.shared.persistentContainer.viewContext
  17. injectServices(FreeAPSApp.resolver)
  18. }
  19. func handleRemoteNotification(pushMessage: PushMessage) async {
  20. let isTrioRemoteControlEnabled = UserDefaults.standard.bool(forKey: "isTrioRemoteControlEnabled")
  21. guard isTrioRemoteControlEnabled else {
  22. await logError("Remote command received, but remote control is disabled in settings. Ignoring the command.")
  23. return
  24. }
  25. let currentTime = Date().timeIntervalSince1970
  26. let timeDifference = currentTime - pushMessage.timestamp
  27. if timeDifference > timeWindow {
  28. await logError(
  29. "Command rejected: the message is too old (sent \(Int(timeDifference)) seconds ago, which exceeds the allowed limit).",
  30. pushMessage: pushMessage
  31. )
  32. return
  33. } else if timeDifference < -timeWindow {
  34. await logError(
  35. "Command rejected: the message has an invalid future timestamp (timestamp is \(Int(-timeDifference)) seconds ahead of the current time).",
  36. pushMessage: pushMessage
  37. )
  38. return
  39. }
  40. debug(.remoteControl, "Command received with acceptable time difference: \(Int(timeDifference)) seconds.")
  41. let storedSecret = UserDefaults.standard.string(forKey: "trioRemoteControlSharedSecret") ?? ""
  42. guard !storedSecret.isEmpty else {
  43. await logError(
  44. "Command rejected: shared secret is missing in settings. Cannot authenticate the command.",
  45. pushMessage: pushMessage
  46. )
  47. return
  48. }
  49. guard pushMessage.sharedSecret == storedSecret else {
  50. await logError(
  51. "Command rejected: shared secret does not match. Cannot authenticate the command.",
  52. pushMessage: pushMessage
  53. )
  54. return
  55. }
  56. switch pushMessage.commandType {
  57. case .bolus:
  58. await handleBolusCommand(pushMessage)
  59. case .tempTarget:
  60. await handleTempTargetCommand(pushMessage)
  61. case .cancelTempTarget:
  62. await cancelTempTarget(pushMessage)
  63. case .meal:
  64. await handleMealCommand(pushMessage)
  65. if pushMessage.bolusAmount != nil {
  66. await handleBolusCommand(pushMessage)
  67. }
  68. case .startOverride:
  69. await handleStartOverrideCommand(pushMessage)
  70. case .cancelOverride:
  71. await handleCancelOverrideCommand(pushMessage)
  72. }
  73. }
  74. }
  75. // MARK: - CommandType Enum
  76. extension TrioRemoteControl {
  77. enum CommandType: String, Codable {
  78. case bolus
  79. case tempTarget = "temp_target"
  80. case cancelTempTarget = "cancel_temp_target"
  81. case meal
  82. case startOverride = "start_override"
  83. case cancelOverride = "cancel_override"
  84. var description: String {
  85. switch self {
  86. case .bolus:
  87. return "Bolus"
  88. case .tempTarget:
  89. return "Temporary Target"
  90. case .cancelTempTarget:
  91. return "Cancel Temporary Target"
  92. case .meal:
  93. return "Meal"
  94. case .startOverride:
  95. return "Start Override"
  96. case .cancelOverride:
  97. return "Cancel Override"
  98. }
  99. }
  100. }
  101. }