DeviceDataManager.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import Combine
  2. import Foundation
  3. import LoopKit
  4. import LoopKitUI
  5. import MinimedKit
  6. import MockKit
  7. import OmniKit
  8. import SwiftDate
  9. import Swinject
  10. import UserNotifications
  11. protocol DeviceDataManager {
  12. var pumpManager: PumpManagerUI? { get set }
  13. var pumpDisplayState: CurrentValueSubject<PumpDisplayState?, Never> { get }
  14. }
  15. private let staticPumpManagers: [PumpManagerUI.Type] = [
  16. MinimedPumpManager.self,
  17. OmnipodPumpManager.self,
  18. MockPumpManager.self
  19. ]
  20. private let staticPumpManagersByIdentifier: [String: PumpManagerUI.Type] = staticPumpManagers.reduce(into: [:]) { map, Type in
  21. map[Type.managerIdentifier] = Type
  22. }
  23. final class BaseDeviceDataManager: DeviceDataManager, Injectable {
  24. @Injected() private var pumpHistoryStorage: PumpHistoryStorage!
  25. @Injected() private var storage: FileStorage!
  26. @Persisted(key: "BaseDeviceDataManager.lastEventDate") var lastEventDate: Date? = nil
  27. var pumpManager: PumpManagerUI? {
  28. didSet {
  29. pumpManager?.pumpManagerDelegate = self
  30. UserDefaults.standard.pumpManagerRawValue = pumpManager?.rawValue
  31. if let pumpManager = pumpManager {
  32. pumpDisplayState.value = PumpDisplayState(name: pumpManager.localizedTitle, image: pumpManager.smallImage)
  33. } else {
  34. pumpDisplayState.value = nil
  35. }
  36. }
  37. }
  38. let pumpDisplayState = CurrentValueSubject<PumpDisplayState?, Never>(nil)
  39. init(resolver: Resolver) {
  40. injectServices(resolver)
  41. setupPumpManager()
  42. }
  43. func setupPumpManager() {
  44. if let pumpManagerRawValue = UserDefaults.standard.pumpManagerRawValue {
  45. pumpManager = pumpManagerFromRawValue(pumpManagerRawValue)
  46. }
  47. }
  48. private func pumpManagerFromRawValue(_ rawValue: [String: Any]) -> PumpManagerUI? {
  49. guard let rawState = rawValue["state"] as? PumpManager.RawStateValue,
  50. let Manager = pumpManagerTypeFromRawValue(rawValue)
  51. else {
  52. return nil
  53. }
  54. return Manager.init(rawState: rawState) as? PumpManagerUI
  55. }
  56. private func pumpManagerTypeFromRawValue(_ rawValue: [String: Any]) -> PumpManager.Type? {
  57. guard let managerIdentifier = rawValue["managerIdentifier"] as? String else {
  58. return nil
  59. }
  60. return staticPumpManagersByIdentifier[managerIdentifier]
  61. }
  62. }
  63. extension BaseDeviceDataManager: PumpManagerDelegate {
  64. func pumpManager(_: PumpManager, didAdjustPumpClockBy _: TimeInterval) {
  65. // log.debug("didAdjustPumpClockBy %@", adjustment)
  66. }
  67. func pumpManagerDidUpdateState(_ pumpManager: PumpManager) {
  68. UserDefaults.standard.pumpManagerRawValue = pumpManager.rawValue
  69. }
  70. func pumpManagerBLEHeartbeatDidFire(_ pumpManager: PumpManager) {
  71. print("[DeviceDataManager] Pump Heartbeat")
  72. pumpManager.ensureCurrentPumpData {
  73. print("[DeviceDataManager] Pump Data updated")
  74. }
  75. }
  76. func pumpManagerMustProvideBLEHeartbeat(_: PumpManager) -> Bool {
  77. true
  78. }
  79. func pumpManager(_: PumpManager, didUpdate status: PumpManagerStatus, oldStatus _: PumpManagerStatus) {
  80. print("[DeviceDataManager] New pump status Bolus: \(status.bolusState)")
  81. print("[DeviceDataManager] New pump status Basal: \(String(describing: status.basalDeliveryState))")
  82. }
  83. func pumpManagerWillDeactivate(_: PumpManager) {
  84. pumpManager = nil
  85. }
  86. func pumpManager(_: PumpManager, didUpdatePumpRecordsBasalProfileStartEvents _: Bool) {}
  87. func pumpManager(_: PumpManager, didError error: PumpManagerError) {
  88. print("[DeviceDataManager] error: \(error.localizedDescription)")
  89. }
  90. func pumpManager(
  91. _: PumpManager,
  92. hasNewPumpEvents events: [NewPumpEvent],
  93. lastReconciliation _: Date?,
  94. completion: @escaping (_ error: Error?) -> Void
  95. ) {
  96. pumpHistoryStorage.storePumpEvents(events)
  97. lastEventDate = events.last?.date
  98. completion(nil)
  99. }
  100. func pumpManager(
  101. _: PumpManager,
  102. didReadReservoirValue units: Double,
  103. at date: Date,
  104. completion: @escaping (Result<
  105. (newValue: ReservoirValue, lastValue: ReservoirValue?, areStoredValuesContinuous: Bool),
  106. Error
  107. >) -> Void
  108. ) {
  109. print("[DeviceDataManager] Reservoir Value \(units), at: \(date)")
  110. try? storage.save(Decimal(units), as: OpenAPS.Monitor.reservoir)
  111. let batteryPercent = Int((pumpManager?.status.pumpBatteryChargeRemaining ?? 1) * 100)
  112. let battery = Battery(percent: batteryPercent, string: batteryPercent >= 10 ? .normal : .low)
  113. try? storage.save(battery, as: OpenAPS.Monitor.battery)
  114. completion(.success((
  115. newValue: Reservoir(startDate: Date(), unitVolume: units),
  116. lastValue: nil,
  117. areStoredValuesContinuous: true
  118. )))
  119. }
  120. func pumpManagerRecommendsLoop(_: PumpManager) {
  121. print("[DeviceDataManager] Recomends loop")
  122. }
  123. func startDateToFilterNewPumpEvents(for _: PumpManager) -> Date {
  124. lastEventDate ?? Date().addingTimeInterval(-2.hours.timeInterval)
  125. }
  126. }
  127. // MARK: - DeviceManagerDelegate
  128. extension BaseDeviceDataManager: DeviceManagerDelegate {
  129. func scheduleNotification(
  130. for _: DeviceManager,
  131. identifier: String,
  132. content: UNNotificationContent,
  133. trigger: UNNotificationTrigger?
  134. ) {
  135. let request = UNNotificationRequest(
  136. identifier: identifier,
  137. content: content,
  138. trigger: trigger
  139. )
  140. DispatchQueue.main.async {
  141. UNUserNotificationCenter.current().add(request)
  142. }
  143. }
  144. func clearNotification(for _: DeviceManager, identifier: String) {
  145. DispatchQueue.main.async {
  146. UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
  147. }
  148. }
  149. func removeNotificationRequests(for _: DeviceManager, identifiers: [String]) {
  150. DispatchQueue.main.async {
  151. UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: identifiers)
  152. }
  153. }
  154. func deviceManager(
  155. _: DeviceManager,
  156. logEventForDeviceIdentifier _: String?,
  157. type _: DeviceLogEntryType,
  158. message _: String,
  159. completion _: ((Error?) -> Void)?
  160. ) {}
  161. }
  162. // MARK: - AlertPresenter
  163. extension BaseDeviceDataManager: AlertPresenter {
  164. func issueAlert(_: Alert) {}
  165. func retractAlert(identifier _: Alert.Identifier) {}
  166. }