dexcomSourceG7.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import Combine
  2. import Foundation
  3. import G7SensorKit
  4. import LoopKit
  5. import LoopKitUI
  6. final class DexcomSourceG7: GlucoseSource {
  7. private let processQueue = DispatchQueue(label: "DexcomSource.processQueue")
  8. private var timer: DispatchTimer?
  9. private var glucoseStorage: GlucoseStorage!
  10. var cgmManager: G7CGMManager
  11. var cgmHasValidSensorSession: Bool = false
  12. private var promise: Future<[BloodGlucose], Error>.Promise?
  13. init(glucoseStorage: GlucoseStorage) {
  14. cgmManager = G7CGMManager()
  15. cgmManager.cgmManagerDelegate = self
  16. self.glucoseStorage = glucoseStorage
  17. }
  18. func fetch(_ heartbeat: DispatchTimer?) -> AnyPublisher<[BloodGlucose], Never> {
  19. // dexcomManager.transmitter.resumeScanning()
  20. timer = heartbeat
  21. return Future<[BloodGlucose], Error> { [weak self] promise in
  22. self?.promise = promise
  23. }
  24. .timeout(60, scheduler: processQueue, options: nil, customError: nil)
  25. .replaceError(with: [])
  26. .replaceEmpty(with: [])
  27. .eraseToAnyPublisher()
  28. }
  29. deinit {
  30. // dexcomManager.transmitter.stopScanning()
  31. }
  32. }
  33. extension DexcomSourceG7: CGMManagerDelegate {
  34. func deviceManager(
  35. _: LoopKit.DeviceManager,
  36. logEventForDeviceIdentifier _: String?,
  37. type _: LoopKit.DeviceLogEntryType,
  38. message _: String,
  39. completion _: ((Error?) -> Void)?
  40. ) {}
  41. func issueAlert(_: LoopKit.Alert) {}
  42. func retractAlert(identifier _: LoopKit.Alert.Identifier) {}
  43. func doesIssuedAlertExist(identifier _: LoopKit.Alert.Identifier, completion _: @escaping (Result<Bool, Error>) -> Void) {}
  44. func lookupAllUnretracted(
  45. managerIdentifier _: String,
  46. completion _: @escaping (Result<[LoopKit.PersistedAlert], Error>) -> Void
  47. ) {}
  48. func lookupAllUnacknowledgedUnretracted(
  49. managerIdentifier _: String,
  50. completion _: @escaping (Result<[LoopKit.PersistedAlert], Error>) -> Void
  51. ) {}
  52. func recordRetractedAlert(_: LoopKit.Alert, at _: Date) {}
  53. func cgmManagerWantsDeletion(_: CGMManager) {}
  54. func cgmManager(_ manager: CGMManager, hasNew readingResult: CGMReadingResult) {
  55. dispatchPrecondition(condition: .onQueue(.main))
  56. processCGMReadingResult(manager, readingResult: readingResult) {
  57. // self.checkPumpDataAndLoop()
  58. }
  59. }
  60. func startDateToFilterNewData(for _: CGMManager) -> Date? {
  61. dispatchPrecondition(condition: .onQueue(.main))
  62. return glucoseStorage.lastGlucoseDate()
  63. // return glucoseStore.latestGlucose?.startDate
  64. }
  65. func cgmManagerDidUpdateState(_: CGMManager) {}
  66. func credentialStoragePrefix(for _: CGMManager) -> String {
  67. // return string unique to this instance of the CGMManager
  68. UUID().uuidString
  69. }
  70. func cgmManager(_: CGMManager, didUpdate status: CGMManagerStatus) {
  71. DispatchQueue.main.async {
  72. if self.cgmHasValidSensorSession != status.hasValidSensorSession {
  73. self.cgmHasValidSensorSession = status.hasValidSensorSession
  74. }
  75. }
  76. }
  77. private func processCGMReadingResult(_: CGMManager, readingResult: CGMReadingResult, completion: @escaping () -> Void) {
  78. warning(.deviceManager, "DEXCOMG7 - Process CGM Reading Result launched")
  79. switch readingResult {
  80. case let .newData(values):
  81. let bloodGlucose = values.compactMap { newGlucoseSample -> BloodGlucose? in
  82. let quantity = newGlucoseSample.quantity
  83. let value = Int(quantity.doubleValue(for: .milligramsPerDeciliter))
  84. return BloodGlucose(
  85. _id: newGlucoseSample.syncIdentifier,
  86. sgv: value,
  87. direction: .init(trendType: newGlucoseSample.trend),
  88. date: Decimal(Int(newGlucoseSample.date.timeIntervalSince1970 * 1000)),
  89. dateString: newGlucoseSample.date,
  90. unfiltered: nil,
  91. filtered: nil,
  92. noise: nil,
  93. glucose: value,
  94. type: "sgv"
  95. )
  96. }
  97. promise?(.success(bloodGlucose))
  98. completion()
  99. case .unreliableData:
  100. // loopManager.receivedUnreliableCGMReading()
  101. promise?(.failure(GlucoseDataError.unreliableData))
  102. completion()
  103. case .noData:
  104. promise?(.failure(GlucoseDataError.noData))
  105. completion()
  106. case let .error(error):
  107. promise?(.failure(error))
  108. completion()
  109. }
  110. }
  111. }
  112. // extension DexcomSourceG7 {
  113. // func sourceInfo() -> [String: Any]? {
  114. // [GlucoseSourceKey.description.rawValue: "Dexcom tramsmitter ID: \(transmitterID)"]
  115. // }
  116. // }