DeviceDataManager.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import Foundation
  2. import LoopKit
  3. import LoopKitUI
  4. import MinimedKit
  5. import MinimedKitUI
  6. import NightscoutUploadKit
  7. import OmniKit
  8. import RileyLinkBLEKit
  9. import RileyLinkKit
  10. import RileyLinkKitUI
  11. import SwiftDate
  12. import UserNotifications
  13. protocol DeviceDataManager {
  14. var rileyLinkConnectionManager: RileyLinkConnectionManager! { get }
  15. var pumpManager: PumpManagerUI? { get set }
  16. }
  17. final class BaseDeviceManager: DeviceDataManager {
  18. private(set) var rileyLinkConnectionManager: RileyLinkConnectionManager!
  19. var pumpManager: PumpManagerUI? {
  20. didSet {
  21. pumpManager?.pumpManagerDelegate = self
  22. UserDefaults.standard.pumpManagerRawValue = pumpManager?.rawValue
  23. }
  24. }
  25. @Persisted(key: "BaseDeviceManager.connectionState") var connectionState: RileyLinkConnectionManagerState? = nil
  26. init() {
  27. if let state = connectionState {
  28. rileyLinkConnectionManager = RileyLinkConnectionManager(state: state)
  29. } else {
  30. rileyLinkConnectionManager = RileyLinkConnectionManager(autoConnectIDs: [])
  31. }
  32. rileyLinkConnectionManager.delegate = self
  33. rileyLinkConnectionManager.setScanningEnabled(true)
  34. if let pumpManagerRawValue = UserDefaults.standard.pumpManagerRawValue {
  35. pumpManager = PumpManagerFromRawValue(
  36. pumpManagerRawValue,
  37. rileyLinkDeviceProvider: rileyLinkConnectionManager.deviceProvider
  38. ) as? PumpManagerUI
  39. pumpManager?.pumpManagerDelegate = self
  40. }
  41. }
  42. }
  43. extension BaseDeviceManager: RileyLinkConnectionManagerDelegate {
  44. func rileyLinkConnectionManager(_: RileyLinkConnectionManager, didChange state: RileyLinkConnectionManagerState)
  45. {
  46. connectionState = state
  47. }
  48. }
  49. extension BaseDeviceManager: PumpManagerDelegate {
  50. func pumpManager(_: PumpManager, didAdjustPumpClockBy _: TimeInterval) {
  51. // log.debug("didAdjustPumpClockBy %@", adjustment)
  52. }
  53. func pumpManagerDidUpdateState(_ pumpManager: PumpManager) {
  54. UserDefaults.standard.pumpManagerRawValue = pumpManager.rawValue
  55. }
  56. func pumpManagerBLEHeartbeatDidFire(_: PumpManager) {}
  57. func pumpManagerMustProvideBLEHeartbeat(_: PumpManager) -> Bool {
  58. true
  59. }
  60. func pumpManager(_: PumpManager, didUpdate _: PumpManagerStatus, oldStatus _: PumpManagerStatus) {}
  61. func pumpManagerWillDeactivate(_: PumpManager) {
  62. pumpManager = nil
  63. }
  64. func pumpManager(_: PumpManager, didUpdatePumpRecordsBasalProfileStartEvents _: Bool) {}
  65. func pumpManager(_: PumpManager, didError _: PumpManagerError) {
  66. // log.error("pumpManager didError %@", String(describing: error))
  67. }
  68. func pumpManager(
  69. _: PumpManager,
  70. hasNewPumpEvents _: [NewPumpEvent],
  71. lastReconciliation _: Date?,
  72. completion _: @escaping (_ error: Error?) -> Void
  73. ) {}
  74. func pumpManager(
  75. _: PumpManager,
  76. didReadReservoirValue _: Double,
  77. at _: Date,
  78. completion _: @escaping (Result<
  79. (newValue: ReservoirValue, lastValue: ReservoirValue?, areStoredValuesContinuous: Bool),
  80. Error
  81. >) -> Void
  82. ) {}
  83. func pumpManagerRecommendsLoop(_: PumpManager) {}
  84. func startDateToFilterNewPumpEvents(for _: PumpManager) -> Date {
  85. Date().addingTimeInterval(-2.hours.timeInterval)
  86. }
  87. }
  88. // MARK: - DeviceManagerDelegate
  89. extension BaseDeviceManager: DeviceManagerDelegate {
  90. func scheduleNotification(
  91. for _: DeviceManager,
  92. identifier: String,
  93. content: UNNotificationContent,
  94. trigger: UNNotificationTrigger?
  95. ) {
  96. let request = UNNotificationRequest(
  97. identifier: identifier,
  98. content: content,
  99. trigger: trigger
  100. )
  101. DispatchQueue.main.async {
  102. UNUserNotificationCenter.current().add(request)
  103. }
  104. }
  105. func clearNotification(for _: DeviceManager, identifier: String) {
  106. DispatchQueue.main.async {
  107. UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
  108. }
  109. }
  110. func removeNotificationRequests(for _: DeviceManager, identifiers: [String]) {
  111. DispatchQueue.main.async {
  112. UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: identifiers)
  113. }
  114. }
  115. func deviceManager(
  116. _: DeviceManager,
  117. logEventForDeviceIdentifier _: String?,
  118. type _: DeviceLogEntryType,
  119. message _: String,
  120. completion _: ((Error?) -> Void)?
  121. ) {}
  122. }
  123. // MARK: - AlertPresenter
  124. extension BaseDeviceManager: AlertPresenter {
  125. func issueAlert(_: Alert) {}
  126. func retractAlert(identifier _: Alert.Identifier) {}
  127. }
  128. extension RileyLinkConnectionManagerState: Codable {
  129. enum CodingKeys: CodingKey {
  130. case autoConnectIDs
  131. }
  132. public init(from decoder: Decoder) throws {
  133. let container = try decoder.container(keyedBy: CodingKeys.self)
  134. if let ids = try? container.decode([String].self, forKey: CodingKeys.autoConnectIDs) {
  135. self.init(autoConnectIDs: Set(ids))
  136. return
  137. }
  138. self.init(autoConnectIDs: [])
  139. }
  140. public func encode(to encoder: Encoder) throws {
  141. var container = encoder.container(keyedBy: CodingKeys.self)
  142. try container.encode(Array(autoConnectIDs), forKey: CodingKeys.autoConnectIDs)
  143. }
  144. }
  145. extension PumpManager {
  146. var rawValue: [String: Any] {
  147. [
  148. "managerIdentifier": type(of: self).managerIdentifier,
  149. "state": rawState
  150. ]
  151. }
  152. }
  153. func PumpManagerFromRawValue(_ rawValue: [String: Any], rileyLinkDeviceProvider: RileyLinkDeviceProvider) -> PumpManager? {
  154. guard let managerIdentifier = rawValue["managerIdentifier"] as? String,
  155. let rawState = rawValue["state"] as? PumpManager.RawStateValue
  156. else {
  157. return nil
  158. }
  159. switch managerIdentifier {
  160. case MinimedPumpManager.managerIdentifier:
  161. guard let state = MinimedPumpManagerState(rawValue: rawState) else {
  162. return nil
  163. }
  164. return MinimedPumpManager(state: state, rileyLinkDeviceProvider: rileyLinkDeviceProvider)
  165. case OmnipodPumpManager.managerIdentifier:
  166. guard let state = OmnipodPumpManagerState(rawValue: rawState) else {
  167. return nil
  168. }
  169. return OmnipodPumpManager(state: state, rileyLinkDeviceProvider: rileyLinkDeviceProvider)
  170. default:
  171. return nil
  172. }
  173. }