DeviceDataManager.swift 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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.map(\.title))"
  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. id: event.raw.md5String,
  66. type: .bolus,
  67. timestamp: event.date,
  68. amount: decimal,
  69. duration: nil,
  70. durationMin: nil,
  71. rate: nil,
  72. temp: nil
  73. )]
  74. default:
  75. return []
  76. }
  77. }
  78. do {
  79. try storage.append(eventsToStore, to: OpenAPS.Monitor.pumpHistory, uniqBy: \.id)
  80. } catch {
  81. try? storage.save(eventsToStore, as: OpenAPS.Monitor.pumpHistory)
  82. }
  83. }
  84. }
  85. extension DeviceDataManager: PumpManagerDelegate {
  86. func pumpManager(_: PumpManager, didAdjustPumpClockBy _: TimeInterval) {
  87. // log.debug("didAdjustPumpClockBy %@", adjustment)
  88. }
  89. func pumpManagerDidUpdateState(_ pumpManager: PumpManager) {
  90. UserDefaults.standard.pumpManagerRawValue = pumpManager.rawValue
  91. }
  92. func pumpManagerBLEHeartbeatDidFire(_ pumpManager: PumpManager) {
  93. print("[DeviceDataManager] Pump Heartbeat")
  94. pumpManager.ensureCurrentPumpData {
  95. print("[DeviceDataManager] Pump Data updated")
  96. }
  97. }
  98. func pumpManagerMustProvideBLEHeartbeat(_: PumpManager) -> Bool {
  99. true
  100. }
  101. func pumpManager(_: PumpManager, didUpdate status: PumpManagerStatus, oldStatus _: PumpManagerStatus) {
  102. print("[DeviceDataManager] new pump status Bolus: \(status.bolusState)")
  103. print("[DeviceDataManager] new pump status Basal: \(String(describing: status.basalDeliveryState))")
  104. }
  105. func pumpManagerWillDeactivate(_: PumpManager) {
  106. pumpManager = nil
  107. }
  108. func pumpManager(_: PumpManager, didUpdatePumpRecordsBasalProfileStartEvents _: Bool) {}
  109. func pumpManager(_: PumpManager, didError error: PumpManagerError) {
  110. print("[DeviceDataManager] error: \(error.localizedDescription)")
  111. }
  112. func pumpManager(
  113. _: PumpManager,
  114. hasNewPumpEvents events: [NewPumpEvent],
  115. lastReconciliation _: Date?,
  116. completion: @escaping (_ error: Error?) -> Void
  117. ) {
  118. storePumpEvents(events)
  119. completion(nil)
  120. }
  121. func pumpManager(
  122. _: PumpManager,
  123. didReadReservoirValue units: Double,
  124. at date: Date,
  125. completion: @escaping (Result<
  126. (newValue: ReservoirValue, lastValue: ReservoirValue?, areStoredValuesContinuous: Bool),
  127. Error
  128. >) -> Void
  129. ) {
  130. print("[DeviceDataManager] Reservoir Value \(units), at: \(date)")
  131. completion(.success((
  132. newValue: Reservoir(startDate: Date(), unitVolume: units),
  133. lastValue: nil,
  134. areStoredValuesContinuous: true
  135. )))
  136. }
  137. func pumpManagerRecommendsLoop(_: PumpManager) {
  138. print("[DeviceDataManager] recomends loop")
  139. // pumpManager.enactBolus(units: 0.1, automatic: true) { _ in
  140. // print("[DeviceDataManager] Bolus done")
  141. // }
  142. }
  143. func startDateToFilterNewPumpEvents(for _: PumpManager) -> Date {
  144. Date().addingTimeInterval(-2.hours.timeInterval)
  145. }
  146. }
  147. // MARK: - DeviceManagerDelegate
  148. extension DeviceDataManager: DeviceManagerDelegate {
  149. func scheduleNotification(
  150. for _: DeviceManager,
  151. identifier: String,
  152. content: UNNotificationContent,
  153. trigger: UNNotificationTrigger?
  154. ) {
  155. let request = UNNotificationRequest(
  156. identifier: identifier,
  157. content: content,
  158. trigger: trigger
  159. )
  160. DispatchQueue.main.async {
  161. UNUserNotificationCenter.current().add(request)
  162. }
  163. }
  164. func clearNotification(for _: DeviceManager, identifier: String) {
  165. DispatchQueue.main.async {
  166. UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
  167. }
  168. }
  169. func removeNotificationRequests(for _: DeviceManager, identifiers: [String]) {
  170. DispatchQueue.main.async {
  171. UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: identifiers)
  172. }
  173. }
  174. func deviceManager(
  175. _: DeviceManager,
  176. logEventForDeviceIdentifier _: String?,
  177. type _: DeviceLogEntryType,
  178. message _: String,
  179. completion _: ((Error?) -> Void)?
  180. ) {}
  181. }
  182. // MARK: - AlertPresenter
  183. extension DeviceDataManager: AlertPresenter {
  184. func issueAlert(_: Alert) {}
  185. func retractAlert(identifier _: Alert.Identifier) {}
  186. }