TrioRemoteControl+Bolus.swift 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import Foundation
  2. import HealthKit
  3. extension TrioRemoteControl {
  4. func handleBolusCommand(_ payload: CommandPayload) async throws {
  5. guard let bolusAmount = payload.bolusAmount else {
  6. await logError("Command rejected: bolus amount is missing or invalid.", payload: payload)
  7. return
  8. }
  9. let validation = try await bolusSafetyValidator.validate(
  10. bolusAmount: bolusAmount,
  11. lookbackStart: Date(timeIntervalSince1970: payload.timestamp)
  12. )
  13. switch validation {
  14. case .allowed:
  15. break
  16. case let .rejected(reason):
  17. await logError(reason.remoteCommandMessage(bolusAmount: bolusAmount), payload: payload)
  18. return
  19. }
  20. debug(.remoteControl, "Enacting bolus command with amount: \(bolusAmount) units.")
  21. guard let apsManager = await TrioApp.resolver.resolve(APSManager.self) else {
  22. await logError(
  23. "Error: unable to process bolus command because the APS Manager is not available.",
  24. payload: payload
  25. )
  26. return
  27. }
  28. if let returnInfo = payload.returnNotification {
  29. await RemoteNotificationResponseManager.shared.sendResponseNotification(
  30. to: returnInfo,
  31. commandType: payload.commandType,
  32. success: true,
  33. message: "Initiating bolus..."
  34. )
  35. }
  36. await apsManager
  37. .enactBolus(amount: Double(truncating: bolusAmount as NSNumber), isSMB: false) { [weak self] success, message in
  38. guard let self = self else { return }
  39. Task {
  40. if success {
  41. await self.logSuccess(
  42. "Remote command processed successfully. \(payload.humanReadableDescription())",
  43. payload: payload,
  44. customNotificationMessage: "Bolus started"
  45. )
  46. } else {
  47. await self.logError(
  48. message,
  49. payload: payload
  50. )
  51. }
  52. }
  53. }
  54. }
  55. }
  56. private extension BolusSafetyRejection {
  57. func remoteCommandMessage(bolusAmount: Decimal) -> String {
  58. switch self {
  59. case let .exceedsMaxBolus(maxBolus):
  60. return "Command rejected: bolus amount (\(bolusAmount) units) exceeds the maximum allowed (\(maxBolus) units)."
  61. case .iobUnavailable:
  62. return "Command rejected: current IOB is not available."
  63. case let .exceedsMaxIOB(currentIOB, maxIOB):
  64. return "Command rejected: bolus amount (\(bolusAmount) units) would exceed max IOB (\(maxIOB) units). Current IOB: \(currentIOB) units."
  65. case .recentBolusWithinWindow:
  66. return "Command rejected: boluses totaling more than 20% of the requested amount have been delivered since the command was sent."
  67. }
  68. }
  69. }