DeviceDataManager.swift 6.8 KB

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