BaseDeviceDataManager.swift 6.5 KB

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