DeviceDataManager.swift 6.3 KB

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