BaseAPSManager.swift 6.0 KB

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