StateIntentRequest.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 StateiAPSResults: AppEntity {
  9. static var defaultQuery = StateBGQuery()
  10. static var typeDisplayRepresentation: TypeDisplayRepresentation = "iAPS 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 _: [StateiAPSResults.ID]) async throws -> [StateiAPSResults] {
  35. []
  36. }
  37. func suggestedEntities() async throws -> [StateiAPSResults] {
  38. []
  39. }
  40. }
  41. @available(iOS 16.0, *) final class StateIntentRequest: BaseIntentsRequest {
  42. func getLastBG() throws -> (dateGlucose: Date, glucose: String, trend: String, delta: String) {
  43. let glucose = glucoseStorage.recent()
  44. guard let lastGlucose = glucose.last, let glucoseValue = lastGlucose.glucose else { throw StateIntentError.NoBG }
  45. let delta = glucose.count >= 2 ? glucoseValue - (glucose[glucose.count - 2].glucose ?? 0) : nil
  46. let units = settingsManager.settings.units
  47. let glucoseText = glucoseFormatter
  48. .string(from: Double(
  49. units == .mmolL ? glucoseValue
  50. .asMmolL : Decimal(glucoseValue)
  51. ) as NSNumber)!
  52. let directionText = lastGlucose.direction?.rawValue ?? "none"
  53. let deltaText = delta
  54. .map {
  55. self.deltaFormatter
  56. .string(from: Double(
  57. units == .mmolL ? $0
  58. .asMmolL : Decimal($0)
  59. ) as NSNumber)!
  60. } ?? "--"
  61. return (lastGlucose.dateString, glucoseText, directionText, deltaText)
  62. }
  63. func getIOB_COB() throws -> (iob: Double, cob: Double) {
  64. let iob = suggestion?.iob ?? 0.0
  65. let cob = suggestion?.cob ?? 0.0
  66. let iob_double = Double(truncating: iob as NSNumber)
  67. let cob_double = Double(truncating: cob as NSNumber)
  68. return (iob_double, cob_double)
  69. }
  70. private var suggestion: Suggestion? {
  71. fileStorage.retrieve(OpenAPS.Enact.suggested, as: Suggestion.self)
  72. }
  73. private var glucoseFormatter: NumberFormatter {
  74. let formatter = NumberFormatter()
  75. formatter.numberStyle = .decimal
  76. formatter.maximumFractionDigits = 0
  77. if settingsManager.settings.units == .mmolL {
  78. formatter.minimumFractionDigits = 1
  79. formatter.maximumFractionDigits = 1
  80. }
  81. formatter.roundingMode = .halfUp
  82. return formatter
  83. }
  84. private var deltaFormatter: NumberFormatter {
  85. let formatter = NumberFormatter()
  86. formatter.numberStyle = .decimal
  87. formatter.maximumFractionDigits = 1
  88. formatter.positivePrefix = "+"
  89. return formatter
  90. }
  91. }