| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- import CoreData
- import Foundation
- import Swinject
- class TrioRemoteControl: Injectable {
- static let shared = TrioRemoteControl()
- @Injected() internal var tempTargetsStorage: TempTargetsStorage!
- @Injected() internal var carbsStorage: CarbsStorage!
- @Injected() internal var nightscoutManager: NightscoutManager!
- @Injected() internal var overrideStorage: OverrideStorage!
- @Injected() internal var settings: SettingsManager!
- private let timeWindow: TimeInterval = 600 // Defines how old messages that are accepted, 10 minutes
- internal let pumpHistoryFetchContext: NSManagedObjectContext
- internal let viewContext: NSManagedObjectContext
- private init() {
- pumpHistoryFetchContext = CoreDataStack.shared.newTaskContext()
- viewContext = CoreDataStack.shared.persistentContainer.viewContext
- injectServices(FreeAPSApp.resolver)
- }
- func handleRemoteNotification(pushMessage: PushMessage) async {
- let isTrioRemoteControlEnabled = UserDefaults.standard.bool(forKey: "isTrioRemoteControlEnabled")
- guard isTrioRemoteControlEnabled else {
- await logError("Remote command received, but remote control is disabled in settings. Ignoring the command.")
- return
- }
- let currentTime = Date().timeIntervalSince1970
- let timeDifference = currentTime - pushMessage.timestamp
- if timeDifference > timeWindow {
- await logError(
- "Command rejected: the message is too old (sent \(Int(timeDifference)) seconds ago, which exceeds the allowed limit).",
- pushMessage: pushMessage
- )
- return
- } else if timeDifference < -timeWindow {
- await logError(
- "Command rejected: the message has an invalid future timestamp (timestamp is \(Int(-timeDifference)) seconds ahead of the current time).",
- pushMessage: pushMessage
- )
- return
- }
- debug(.remoteControl, "Command received with acceptable time difference: \(Int(timeDifference)) seconds.")
- let storedSecret = UserDefaults.standard.string(forKey: "trioRemoteControlSharedSecret") ?? ""
- guard !storedSecret.isEmpty else {
- await logError(
- "Command rejected: shared secret is missing in settings. Cannot authenticate the command.",
- pushMessage: pushMessage
- )
- return
- }
- guard pushMessage.sharedSecret == storedSecret else {
- await logError(
- "Command rejected: shared secret does not match. Cannot authenticate the command.",
- pushMessage: pushMessage
- )
- return
- }
- switch pushMessage.commandType {
- case .bolus:
- await handleBolusCommand(pushMessage)
- case .tempTarget:
- await handleTempTargetCommand(pushMessage)
- case .cancelTempTarget:
- await cancelTempTarget(pushMessage)
- case .meal:
- await handleMealCommand(pushMessage)
- if pushMessage.bolusAmount != nil {
- await handleBolusCommand(pushMessage)
- }
- case .startOverride:
- await handleStartOverrideCommand(pushMessage)
- case .cancelOverride:
- await handleCancelOverrideCommand(pushMessage)
- }
- }
- }
- // MARK: - CommandType Enum
- extension TrioRemoteControl {
- enum CommandType: String, Codable {
- case bolus
- case tempTarget = "temp_target"
- case cancelTempTarget = "cancel_temp_target"
- case meal
- case startOverride = "start_override"
- case cancelOverride = "cancel_override"
- var description: String {
- switch self {
- case .bolus:
- return "Bolus"
- case .tempTarget:
- return "Temporary Target"
- case .cancelTempTarget:
- return "Cancel Temporary Target"
- case .meal:
- return "Meal"
- case .startOverride:
- return "Start Override"
- case .cancelOverride:
- return "Cancel Override"
- }
- }
- }
- }
|