StateIntentRequest.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import AppIntents
  2. import Foundation
  3. enum StateIntentError: Error {
  4. case StateIntentUnknownError
  5. case NoBG
  6. case NoIOBCOB
  7. }
  8. @available(iOS 16, *) struct StateResults: AppEntity {
  9. static var defaultQuery = StateBGQuery()
  10. static var typeDisplayRepresentation: TypeDisplayRepresentation = "Trio State Result"
  11. var displayRepresentation: DisplayRepresentation {
  12. DisplayRepresentation(title: "\(glucose)")
  13. }
  14. var id: UUID
  15. @Property(title: "Glucose") var glucose: String
  16. @Property(title: "Trend") var trend: String
  17. @Property(title: "Delta") var delta: String
  18. @Property(title: "Date") var date: Date
  19. @Property(title: "IOB") var iob: Double?
  20. @Property(title: "COB") var cob: Double?
  21. @Property(title: "unit") var unit: String?
  22. init(glucose: String, trend: String, delta: String, date: Date, iob: Double, cob: Double, unit: GlucoseUnits) {
  23. id = UUID()
  24. self.glucose = glucose
  25. self.trend = trend
  26. self.delta = delta
  27. self.date = date
  28. self.iob = iob
  29. self.cob = cob
  30. self.unit = unit.rawValue
  31. }
  32. }
  33. @available(iOS 16.0, *) struct StateBGQuery: EntityQuery {
  34. func entities(for _: [StateResults.ID]) async throws -> [StateResults] {
  35. []
  36. }
  37. func suggestedEntities() async throws -> [StateResults] {
  38. []
  39. }
  40. }
  41. @available(iOS 16.0, *) final class StateIntentRequest: BaseIntentsRequest {
  42. @Injected() private var glucoseStorage: GlucoseStorage!
  43. @Injected() private var carbsStorage: CarbsStorage!
  44. @Injected() private var apsManager: APSManager!
  45. func getLastBG() throws -> (dateGlucose: Date, glucose: String, trend: String, delta: String) {
  46. let glucose = glucoseStorage.recent()
  47. guard let lastGlucose = glucose.last, let glucoseValue = lastGlucose.glucose else { throw StateIntentError.NoBG }
  48. let delta = glucose.count >= 2 ? glucoseValue - (glucose[glucose.count - 2].glucose ?? 0) : nil
  49. let units = settingsManager.settings.units
  50. let glucoseText = glucoseFormatter
  51. .string(from: Double(
  52. units == .mmolL ? glucoseValue
  53. .asMmolL : Decimal(glucoseValue)
  54. ) as NSNumber)!
  55. let directionText = lastGlucose.direction?.rawValue ?? "none"
  56. let deltaText = delta
  57. .map {
  58. self.deltaFormatter
  59. .string(from: Double(
  60. units == .mmolL ? $0
  61. .asMmolL : Decimal($0)
  62. ) as NSNumber)!
  63. } ?? "--"
  64. return (lastGlucose.dateString, glucoseText, directionText, deltaText)
  65. }
  66. func getIOB_COB() throws -> (iob: Double, cob: Double) {
  67. let iob = suggestion?.iob ?? 0.0
  68. let cob = suggestion?.cob ?? 0.0
  69. let iob_double = Double(truncating: iob as NSNumber)
  70. let cob_double = Double(truncating: cob as NSNumber)
  71. return (iob_double, cob_double)
  72. }
  73. private var suggestion: Suggestion? {
  74. fileStorage.retrieve(OpenAPS.Enact.suggested, as: Suggestion.self)
  75. }
  76. private var glucoseFormatter: NumberFormatter {
  77. let formatter = NumberFormatter()
  78. formatter.numberStyle = .decimal
  79. formatter.maximumFractionDigits = 0
  80. if settingsManager.settings.units == .mmolL {
  81. formatter.minimumFractionDigits = 1
  82. formatter.maximumFractionDigits = 1
  83. }
  84. formatter.roundingMode = .halfUp
  85. return formatter
  86. }
  87. private var deltaFormatter: NumberFormatter {
  88. let formatter = NumberFormatter()
  89. formatter.numberStyle = .decimal
  90. formatter.maximumFractionDigits = 1
  91. formatter.positivePrefix = "+"
  92. return formatter
  93. }
  94. }