OmnipodHUDProvider.swift 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //
  2. // OmnipodHUDProvider.swift
  3. // OmniKitUI
  4. //
  5. // Created by Pete Schwamb on 11/26/18.
  6. // Copyright © 2018 Pete Schwamb. All rights reserved.
  7. //
  8. import UIKit
  9. import SwiftUI
  10. import LoopKit
  11. import LoopKitUI
  12. import OmniKit
  13. internal class OmnipodHUDProvider: NSObject, HUDProvider, PodStateObserver {
  14. var managerIdentifier: String {
  15. return OmnipodPumpManager.managerIdentifier
  16. }
  17. private var podState: PodState? {
  18. didSet {
  19. guard visible else {
  20. return
  21. }
  22. guard oldValue != podState else {
  23. return
  24. }
  25. if oldValue?.lastInsulinMeasurements != podState?.lastInsulinMeasurements {
  26. updateReservoirView()
  27. }
  28. if oldValue != nil && podState == nil {
  29. updateReservoirView()
  30. }
  31. }
  32. }
  33. private let pumpManager: OmnipodPumpManager
  34. private var reservoirView: OmnipodReservoirView?
  35. var visible: Bool = false {
  36. didSet {
  37. if oldValue != visible && visible {
  38. hudDidAppear()
  39. }
  40. }
  41. }
  42. private let insulinTintColor: Color
  43. private let guidanceColors: GuidanceColors
  44. private let allowedInsulinTypes: [InsulinType]
  45. public init(pumpManager: OmnipodPumpManager, insulinTintColor: Color, guidanceColors: GuidanceColors, allowedInsulinTypes: [InsulinType]) {
  46. self.pumpManager = pumpManager
  47. self.podState = pumpManager.state.podState
  48. self.insulinTintColor = insulinTintColor
  49. self.guidanceColors = guidanceColors
  50. self.allowedInsulinTypes = allowedInsulinTypes
  51. super.init()
  52. self.pumpManager.addPodStateObserver(self, queue: .main)
  53. }
  54. private func updateReservoirView() {
  55. if let lastInsulinMeasurements = podState?.lastInsulinMeasurements,
  56. let reservoirView = reservoirView,
  57. let podState = podState
  58. {
  59. let reservoirVolume = lastInsulinMeasurements.reservoirLevel
  60. let reservoirLevel = reservoirVolume?.asReservoirPercentage()
  61. var reservoirAlertState: ReservoirAlertState = .ok
  62. for (_, alert) in podState.activeAlerts {
  63. if case .lowReservoirAlarm = alert {
  64. reservoirAlertState = .lowReservoir
  65. break
  66. }
  67. }
  68. reservoirView.update(volume: reservoirVolume, at: lastInsulinMeasurements.validTime, level: reservoirLevel, reservoirAlertState: reservoirAlertState)
  69. }
  70. }
  71. public func createHUDView() -> LevelHUDView? {
  72. self.reservoirView = OmnipodReservoirView.instantiate()
  73. self.updateReservoirView()
  74. return reservoirView
  75. }
  76. public func didTapOnHUDView(_ view: BaseHUDView) -> HUDTapAction? {
  77. if let podState = self.podState, podState.isFaulted {
  78. return HUDTapAction.presentViewController(PodReplacementNavigationController.instantiatePodReplacementFlow(pumpManager))
  79. } else {
  80. return HUDTapAction.presentViewController(pumpManager.settingsViewController(insulinTintColor: insulinTintColor, guidanceColors: guidanceColors, allowedInsulinTypes: allowedInsulinTypes))
  81. }
  82. }
  83. func hudDidAppear() {
  84. updateReservoirView()
  85. pumpManager.refreshStatus(emitConfirmationBeep: false)
  86. }
  87. public var hudViewRawState: HUDProvider.HUDViewRawState {
  88. var rawValue: HUDProvider.HUDViewRawState = [:]
  89. if let podState = podState {
  90. rawValue["alerts"] = podState.activeAlerts.values.map { $0.rawValue }
  91. }
  92. if let lastInsulinMeasurements = podState?.lastInsulinMeasurements {
  93. rawValue["reservoirVolume"] = lastInsulinMeasurements.reservoirLevel
  94. rawValue["validTime"] = lastInsulinMeasurements.validTime
  95. }
  96. return rawValue
  97. }
  98. public static func createHUDView(rawValue: HUDProvider.HUDViewRawState) -> LevelHUDView? {
  99. guard let rawAlerts = rawValue["alerts"] as? [PodAlert.RawValue] else {
  100. return nil
  101. }
  102. let alerts = rawAlerts.compactMap { PodAlert.init(rawValue: $0) }
  103. let reservoirVolume = rawValue["reservoirVolume"] as? Double
  104. let validTime = rawValue["validTime"] as? Date
  105. let reservoirView = OmnipodReservoirView.instantiate()
  106. if let validTime = validTime
  107. {
  108. let reservoirLevel = reservoirVolume?.asReservoirPercentage()
  109. var reservoirAlertState: ReservoirAlertState = .ok
  110. for alert in alerts {
  111. if case .lowReservoirAlarm = alert {
  112. reservoirAlertState = .lowReservoir
  113. }
  114. }
  115. reservoirView.update(volume: reservoirVolume, at: validTime, level: reservoirLevel, reservoirAlertState: reservoirAlertState)
  116. }
  117. return reservoirView
  118. }
  119. func podStateDidUpdate(_ podState: PodState?) {
  120. self.podState = podState
  121. }
  122. }
  123. extension Double {
  124. func asReservoirPercentage() -> Double {
  125. return min(1, max(0, self / Pod.reservoirCapacity))
  126. }
  127. }