|
|
@@ -1,10 +1,13 @@
|
|
|
import Combine
|
|
|
import Foundation
|
|
|
+import LoopKit
|
|
|
import LoopKitUI
|
|
|
import Swinject
|
|
|
-import UIKit
|
|
|
|
|
|
protocol TidePoolManager {
|
|
|
+ func addTidePoolService(service: Service)
|
|
|
+ func getTidePoolServiceUI() -> ServiceUI?
|
|
|
+ func getTidePoolPluginHost() -> PluginHost?
|
|
|
func deleteCarbs(at date: Date, isFPU: Bool?, fpuID: String?, syncID: String)
|
|
|
func deleteInsulin(at date: Date)
|
|
|
func uploadStatus()
|
|
|
@@ -16,17 +19,66 @@ protocol TidePoolManager {
|
|
|
|
|
|
final class BaseTidePoolManager: TidePoolManager, Injectable {
|
|
|
@Injected() private var broadcaster: Broadcaster!
|
|
|
+ @Injected() private var pluginManager: PluginManager!
|
|
|
|
|
|
private let processQueue = DispatchQueue(label: "BaseNetworkManager.processQueue")
|
|
|
private var ping: TimeInterval?
|
|
|
+ private var tidePoolService: RemoteDataService? {
|
|
|
+ didSet {
|
|
|
+ if let tidePoolService = tidePoolService {
|
|
|
+ rawTidePoolManager = tidePoolService.rawValue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
private var lifetime = Lifetime()
|
|
|
|
|
|
+ @PersistedProperty(key: "TidePoolState") var rawTidePoolManager: Service.RawValue?
|
|
|
+
|
|
|
init(resolver: Resolver) {
|
|
|
injectServices(resolver)
|
|
|
+ loadTidePoolManager()
|
|
|
subscribe()
|
|
|
}
|
|
|
|
|
|
+ /// load the TidePool Remote Data Service if available
|
|
|
+ fileprivate func loadTidePoolManager() {
|
|
|
+ if let rawTidePoolManager = rawTidePoolManager {
|
|
|
+ tidePoolService = tidePoolServiceFromRaw(rawTidePoolManager)
|
|
|
+ tidePoolService?.serviceDelegate = self
|
|
|
+ tidePoolService?.stateDelegate = self
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// allows to acces to tidePoolService as a simple ServiceUI
|
|
|
+ func getTidePoolServiceUI() -> ServiceUI? {
|
|
|
+ if let tidePoolService = self.tidePoolService {
|
|
|
+ return tidePoolService as! any ServiceUI as ServiceUI
|
|
|
+ } else {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func getTidePoolPluginHost() -> PluginHost? {
|
|
|
+ self as PluginHost
|
|
|
+ }
|
|
|
+
|
|
|
+ func addTidePoolService(service: Service) {
|
|
|
+ tidePoolService = service as! any RemoteDataService as RemoteDataService
|
|
|
+ }
|
|
|
+
|
|
|
+ /// load the TidePool Remote Data Service from raw storage
|
|
|
+ private func tidePoolServiceFromRaw(_ rawValue: [String: Any]) -> RemoteDataService? {
|
|
|
+ guard let rawState = rawValue["state"] as? Service.RawStateValue,
|
|
|
+ let serviceType = pluginManager.getServiceTypeByIdentifier("TidepoolService")
|
|
|
+ else {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ if let service = serviceType.init(rawState: rawState) {
|
|
|
+ return service as! any RemoteDataService as RemoteDataService
|
|
|
+ } else { return nil }
|
|
|
+ }
|
|
|
+
|
|
|
private func subscribe() {
|
|
|
broadcaster.register(PumpHistoryObserver.self, observer: self)
|
|
|
broadcaster.register(CarbsObserver.self, observer: self)
|
|
|
@@ -63,3 +115,56 @@ extension BaseTidePoolManager: CarbsObserver {
|
|
|
extension BaseTidePoolManager: TempTargetsObserver {
|
|
|
func tempTargetsDidUpdate(_: [TempTarget]) {}
|
|
|
}
|
|
|
+
|
|
|
+extension BaseTidePoolManager: ServiceDelegate {
|
|
|
+ var hostIdentifier: String {
|
|
|
+ "com.loopkit.Loop" // To check
|
|
|
+ }
|
|
|
+
|
|
|
+ var hostVersion: String {
|
|
|
+ var semanticVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
|
|
|
+
|
|
|
+ while semanticVersion.split(separator: ".").count < 3 {
|
|
|
+ semanticVersion += ".0"
|
|
|
+ }
|
|
|
+
|
|
|
+ semanticVersion += "+\(Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String)"
|
|
|
+
|
|
|
+ return semanticVersion
|
|
|
+ }
|
|
|
+
|
|
|
+ func issueAlert(_: LoopKit.Alert) {}
|
|
|
+
|
|
|
+ func retractAlert(identifier _: LoopKit.Alert.Identifier) {}
|
|
|
+
|
|
|
+ func enactRemoteOverride(name _: String, durationTime _: TimeInterval?, remoteAddress _: String) async throws {}
|
|
|
+
|
|
|
+ func cancelRemoteOverride() async throws {}
|
|
|
+
|
|
|
+ func deliverRemoteCarbs(
|
|
|
+ amountInGrams _: Double,
|
|
|
+ absorptionTime _: TimeInterval?,
|
|
|
+ foodType _: String?,
|
|
|
+ startDate _: Date?
|
|
|
+ ) async throws {}
|
|
|
+
|
|
|
+ func deliverRemoteBolus(amountInUnits _: Double) async throws {}
|
|
|
+}
|
|
|
+
|
|
|
+extension BaseTidePoolManager: StatefulPluggableDelegate {
|
|
|
+ func pluginDidUpdateState(_: LoopKit.StatefulPluggable) {}
|
|
|
+
|
|
|
+ func pluginWantsDeletion(_: LoopKit.StatefulPluggable) {}
|
|
|
+}
|
|
|
+
|
|
|
+// Service extension for rawValue
|
|
|
+extension Service {
|
|
|
+ typealias RawValue = [String: Any]
|
|
|
+
|
|
|
+ var rawValue: RawValue {
|
|
|
+ [
|
|
|
+ "serviceIdentifier": pluginIdentifier,
|
|
|
+ "state": rawState
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|