PushMessage.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import Foundation
  2. struct PushMessage: Codable, Sendable {
  3. var user: String
  4. var commandType: TrioRemoteControl.CommandType
  5. var bolusAmount: Decimal?
  6. var target: Int?
  7. var duration: Int?
  8. var carbs: Int?
  9. var protein: Int?
  10. var fat: Int?
  11. var sharedSecret: String
  12. var timestamp: TimeInterval
  13. var overrideName: String?
  14. var scheduledTime: TimeInterval?
  15. enum CodingKeys: String, CodingKey {
  16. case aps
  17. case user
  18. case commandType = "command_type"
  19. case bolusAmount = "bolus_amount"
  20. case target
  21. case duration
  22. case carbs
  23. case protein
  24. case fat
  25. case sharedSecret = "shared_secret"
  26. case timestamp
  27. case overrideName
  28. case scheduledTime = "scheduled_time"
  29. }
  30. func encode(to encoder: Encoder) throws {
  31. var container = encoder.container(keyedBy: CodingKeys.self)
  32. try container.encode(user, forKey: .user)
  33. try container.encode(commandType, forKey: .commandType)
  34. try container.encodeIfPresent(bolusAmount, forKey: .bolusAmount)
  35. try container.encodeIfPresent(target, forKey: .target)
  36. try container.encodeIfPresent(duration, forKey: .duration)
  37. try container.encodeIfPresent(carbs, forKey: .carbs)
  38. try container.encodeIfPresent(protein, forKey: .protein)
  39. try container.encodeIfPresent(fat, forKey: .fat)
  40. try container.encode(sharedSecret, forKey: .sharedSecret)
  41. try container.encode(timestamp, forKey: .timestamp)
  42. try container.encodeIfPresent(overrideName, forKey: .overrideName)
  43. if let scheduledTime = scheduledTime {
  44. try container.encode(scheduledTime, forKey: .scheduledTime)
  45. }
  46. }
  47. init(from decoder: Decoder) throws {
  48. let container = try decoder.container(keyedBy: CodingKeys.self)
  49. user = try container.decode(String.self, forKey: .user)
  50. commandType = try container.decode(TrioRemoteControl.CommandType.self, forKey: .commandType)
  51. bolusAmount = try container.decodeIfPresent(Decimal.self, forKey: .bolusAmount)
  52. target = try container.decodeIfPresent(Int.self, forKey: .target)
  53. duration = try container.decodeIfPresent(Int.self, forKey: .duration)
  54. carbs = try container.decodeIfPresent(Int.self, forKey: .carbs)
  55. protein = try container.decodeIfPresent(Int.self, forKey: .protein)
  56. fat = try container.decodeIfPresent(Int.self, forKey: .fat)
  57. sharedSecret = try container.decode(String.self, forKey: .sharedSecret)
  58. timestamp = try container.decode(TimeInterval.self, forKey: .timestamp)
  59. overrideName = try container.decodeIfPresent(String.self, forKey: .overrideName)
  60. scheduledTime = try container.decodeIfPresent(TimeInterval.self, forKey: .scheduledTime)
  61. }
  62. init(
  63. user: String,
  64. commandType: TrioRemoteControl.CommandType,
  65. bolusAmount: Decimal? = nil,
  66. target: Int? = nil,
  67. duration: Int? = nil,
  68. carbs: Int? = nil,
  69. protein: Int? = nil,
  70. fat: Int? = nil,
  71. sharedSecret: String,
  72. timestamp: TimeInterval,
  73. overrideName: String? = nil,
  74. scheduledTime: TimeInterval? = nil
  75. ) {
  76. self.user = user
  77. self.commandType = commandType
  78. self.bolusAmount = bolusAmount
  79. self.target = target
  80. self.duration = duration
  81. self.carbs = carbs
  82. self.protein = protein
  83. self.fat = fat
  84. self.sharedSecret = sharedSecret
  85. self.timestamp = timestamp
  86. self.overrideName = overrideName
  87. self.scheduledTime = scheduledTime
  88. }
  89. func humanReadableDescription() -> String {
  90. var description = "User: \(user). Command Type: \(commandType.description). "
  91. if let override = overrideName {
  92. description += "Override Name: \(override). "
  93. }
  94. switch commandType {
  95. case .bolus:
  96. if let amount = bolusAmount {
  97. description += "Bolus Amount: \(amount) units."
  98. } else {
  99. description += "Bolus Amount: unknown."
  100. }
  101. case .tempTarget:
  102. let targetDesc = target != nil ? "\(target!) mg/dL" : "unknown target"
  103. let durationDesc = duration != nil ? "\(duration!) minutes" : "unknown duration"
  104. description += "Temp Target: \(targetDesc), Duration: \(durationDesc)."
  105. case .cancelTempTarget:
  106. description += "Cancel Temp Target command."
  107. case .meal:
  108. let carbsDesc = carbs != nil ? "\(carbs!)g carbs" : "unknown carbs"
  109. let fatDesc = fat != nil ? "\(fat!)g fat" : "unknown fat"
  110. let proteinDesc = protein != nil ? "\(protein!)g protein" : "unknown protein"
  111. description += "Meal with \(carbsDesc), \(fatDesc), \(proteinDesc)."
  112. case .startOverride:
  113. if let override = overrideName {
  114. description += "Start Override: \(override)."
  115. } else {
  116. description += "Start Override: unknown override name."
  117. }
  118. case .cancelOverride:
  119. description += "Cancel Override command."
  120. }
  121. if let scheduledTime = scheduledTime {
  122. let date = Date(timeIntervalSince1970: scheduledTime)
  123. let formatter = DateFormatter()
  124. formatter.dateStyle = .short
  125. formatter.timeStyle = .short
  126. let dateString = formatter.string(from: date)
  127. description += " Scheduled for: \(dateString)."
  128. }
  129. return description
  130. }
  131. }