TidepoolManager.swift 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import Combine
  2. import Foundation
  3. import LoopKit
  4. import LoopKitUI
  5. import Swinject
  6. protocol TidePoolManager {
  7. func addTidePoolService(service: Service)
  8. func getTidePoolServiceUI() -> ServiceUI?
  9. func getTidePoolPluginHost() -> PluginHost?
  10. func deleteCarbs(at date: Date, isFPU: Bool?, fpuID: String?, syncID: String)
  11. func deleteInsulin(at date: Date)
  12. func uploadStatus()
  13. func uploadGlucose()
  14. func uploadStatistics(dailystat: Statistics)
  15. func uploadPreferences(_ preferences: Preferences)
  16. func uploadProfileAndSettings(_: Bool)
  17. }
  18. final class BaseTidePoolManager: TidePoolManager, Injectable {
  19. @Injected() private var broadcaster: Broadcaster!
  20. @Injected() private var pluginManager: PluginManager!
  21. private let processQueue = DispatchQueue(label: "BaseNetworkManager.processQueue")
  22. private var ping: TimeInterval?
  23. private var tidePoolService: RemoteDataService? {
  24. didSet {
  25. if let tidePoolService = tidePoolService {
  26. rawTidePoolManager = tidePoolService.rawValue
  27. }
  28. }
  29. }
  30. private var lifetime = Lifetime()
  31. @PersistedProperty(key: "TidePoolState") var rawTidePoolManager: Service.RawValue?
  32. init(resolver: Resolver) {
  33. injectServices(resolver)
  34. loadTidePoolManager()
  35. subscribe()
  36. }
  37. /// load the TidePool Remote Data Service if available
  38. fileprivate func loadTidePoolManager() {
  39. if let rawTidePoolManager = rawTidePoolManager {
  40. tidePoolService = tidePoolServiceFromRaw(rawTidePoolManager)
  41. tidePoolService?.serviceDelegate = self
  42. tidePoolService?.stateDelegate = self
  43. }
  44. }
  45. /// allows to acces to tidePoolService as a simple ServiceUI
  46. func getTidePoolServiceUI() -> ServiceUI? {
  47. if let tidePoolService = self.tidePoolService {
  48. return tidePoolService as! any ServiceUI as ServiceUI
  49. } else {
  50. return nil
  51. }
  52. }
  53. func getTidePoolPluginHost() -> PluginHost? {
  54. self as PluginHost
  55. }
  56. func addTidePoolService(service: Service) {
  57. tidePoolService = service as! any RemoteDataService as RemoteDataService
  58. }
  59. /// load the TidePool Remote Data Service from raw storage
  60. private func tidePoolServiceFromRaw(_ rawValue: [String: Any]) -> RemoteDataService? {
  61. guard let rawState = rawValue["state"] as? Service.RawStateValue,
  62. let serviceType = pluginManager.getServiceTypeByIdentifier("TidepoolService")
  63. else {
  64. return nil
  65. }
  66. if let service = serviceType.init(rawState: rawState) {
  67. return service as! any RemoteDataService as RemoteDataService
  68. } else { return nil }
  69. }
  70. private func subscribe() {
  71. broadcaster.register(PumpHistoryObserver.self, observer: self)
  72. broadcaster.register(CarbsObserver.self, observer: self)
  73. broadcaster.register(TempTargetsObserver.self, observer: self)
  74. }
  75. func sourceInfo() -> [String: Any]? {
  76. nil
  77. }
  78. func deleteCarbs(at _: Date, isFPU _: Bool?, fpuID _: String?, syncID _: String) {}
  79. func deleteInsulin(at _: Date) {}
  80. func uploadStatus() {}
  81. func uploadGlucose() {}
  82. func uploadStatistics(dailystat _: Statistics) {}
  83. func uploadPreferences(_: Preferences) {}
  84. func uploadProfileAndSettings(_: Bool) {}
  85. }
  86. extension BaseTidePoolManager: PumpHistoryObserver {
  87. func pumpHistoryDidUpdate(_: [PumpHistoryEvent]) {}
  88. }
  89. extension BaseTidePoolManager: CarbsObserver {
  90. func carbsDidUpdate(_: [CarbsEntry]) {}
  91. }
  92. extension BaseTidePoolManager: TempTargetsObserver {
  93. func tempTargetsDidUpdate(_: [TempTarget]) {}
  94. }
  95. extension BaseTidePoolManager: ServiceDelegate {
  96. var hostIdentifier: String {
  97. "com.loopkit.Loop" // To check
  98. }
  99. var hostVersion: String {
  100. var semanticVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
  101. while semanticVersion.split(separator: ".").count < 3 {
  102. semanticVersion += ".0"
  103. }
  104. semanticVersion += "+\(Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String)"
  105. return semanticVersion
  106. }
  107. func issueAlert(_: LoopKit.Alert) {}
  108. func retractAlert(identifier _: LoopKit.Alert.Identifier) {}
  109. func enactRemoteOverride(name _: String, durationTime _: TimeInterval?, remoteAddress _: String) async throws {}
  110. func cancelRemoteOverride() async throws {}
  111. func deliverRemoteCarbs(
  112. amountInGrams _: Double,
  113. absorptionTime _: TimeInterval?,
  114. foodType _: String?,
  115. startDate _: Date?
  116. ) async throws {}
  117. func deliverRemoteBolus(amountInUnits _: Double) async throws {}
  118. }
  119. extension BaseTidePoolManager: StatefulPluggableDelegate {
  120. func pluginDidUpdateState(_: LoopKit.StatefulPluggable) {}
  121. func pluginWantsDeletion(_: LoopKit.StatefulPluggable) {}
  122. }
  123. // Service extension for rawValue
  124. extension Service {
  125. typealias RawValue = [String: Any]
  126. var rawValue: RawValue {
  127. [
  128. "serviceIdentifier": pluginIdentifier,
  129. "state": rawState
  130. ]
  131. }
  132. }