@@ -63,8 +63,17 @@ final class DeviceDataManager: CarbStoreDelegate, CarbStoreSyncDelegate, DoseSto
6363 }
6464 }
6565
66+ var fetchEnliteDataEnabled : Bool {
67+ get {
68+ return UserDefaults . standard. fetchEnliteDataEnabled
69+ }
70+ set {
71+ UserDefaults . standard. fetchEnliteDataEnabled = newValue
72+ }
73+ }
74+
6675 var sensorInfo : SensorDisplayable ? {
67- return latestGlucoseG5 ?? latestGlucoseG4 ?? latestGlucoseFromShare ?? latestPumpStatusFromMySentry
76+ return latestGlucoseG5 ?? latestGlucoseG4 ?? latestGlucoseFromShare ?? latestPumpStatusFromMySentry ?? latestEnliteData
6877 }
6978
7079 var latestPumpStatus : RileyLinkKit . PumpStatus ?
@@ -135,6 +144,10 @@ final class DeviceDataManager: CarbStoreDelegate, CarbStoreSyncDelegate, DoseSto
135144
136145 @objc private func receivedRileyLinkTimerTickNotification( _ note: Notification ) {
137146 backfillGlucoseFromShareIfNeeded ( ) {
147+ if UserDefaults . standard. fetchEnliteDataEnabled {
148+ self . assertCurrentEnliteData ( )
149+ }
150+
138151 self . assertCurrentPumpData ( )
139152 }
140153 }
@@ -365,42 +378,43 @@ final class DeviceDataManager: CarbStoreDelegate, CarbStoreSyncDelegate, DoseSto
365378 }
366379 }
367380
381+ private func pumpDataIsStale( ) -> Bool {
382+ // How long should we wait before we poll for new pump data?
383+ let pumpStatusAgeTolerance = rileyLinkManager. idleListeningEnabled ? TimeInterval ( minutes: 11 ) : TimeInterval ( minutes: 4 )
384+
385+ return doseStore. lastReservoirValue == nil
386+ || doseStore. lastReservoirValue!. startDate. timeIntervalSinceNow <= - pumpStatusAgeTolerance
387+ }
388+
368389 /**
369390 Ensures pump data is current by either waking and polling, or ensuring we're listening to sentry packets.
370391 */
371392 private func assertCurrentPumpData( ) {
372- guard let device = rileyLinkManager. firstConnectedDevice else {
393+ guard let device = rileyLinkManager. firstConnectedDevice, pumpDataIsStale ( ) else {
373394 return
374395 }
375396
376397 device. assertIdleListening ( )
377398
378- // How long should we wait before we poll for new pump data?
379- let pumpStatusAgeTolerance = rileyLinkManager. idleListeningEnabled ? TimeInterval ( minutes: 11 ) : TimeInterval ( minutes: 4 )
380-
381- // If we don't yet have pump status, or it's old, poll for it.
382- if doseStore. lastReservoirValue == nil ||
383- doseStore. lastReservoirValue!. startDate. timeIntervalSinceNow <= - pumpStatusAgeTolerance {
384- readPumpData { ( result) in
385- let nsPumpStatus : NightscoutUploadKit . PumpStatus ?
386- switch result {
387- case . success( let ( status, date) ) :
388- self . observeBatteryDuring {
389- self . latestPumpStatus = status
390- }
399+ readPumpData { ( result) in
400+ let nsPumpStatus : NightscoutUploadKit . PumpStatus ?
401+ switch result {
402+ case . success( let ( status, date) ) :
403+ self . observeBatteryDuring {
404+ self . latestPumpStatus = status
405+ }
391406
392- self . updateReservoirVolume ( status. reservoir, at: date, withTimeLeft: nil )
393- let battery = BatteryStatus ( voltage: status. batteryVolts, status: BatteryIndicator ( batteryStatus: status. batteryStatus) )
407+ self . updateReservoirVolume ( status. reservoir, at: date, withTimeLeft: nil )
408+ let battery = BatteryStatus ( voltage: status. batteryVolts, status: BatteryIndicator ( batteryStatus: status. batteryStatus) )
394409
395410
396- nsPumpStatus = NightscoutUploadKit . PumpStatus ( clock: date, pumpID: status. pumpID, iob: nil , battery: battery, suspended: status. suspended, bolusing: status. bolusing, reservoir: status. reservoir)
397- case . failure( let error) :
398- self . troubleshootPumpComms ( using: device)
399- self . nightscoutDataManager. uploadLoopStatus ( loopError: error)
400- nsPumpStatus = nil
401- }
402- self . nightscoutDataManager. uploadDeviceStatus ( nsPumpStatus)
411+ nsPumpStatus = NightscoutUploadKit . PumpStatus ( clock: date, pumpID: status. pumpID, iob: nil , battery: battery, suspended: status. suspended, bolusing: status. bolusing, reservoir: status. reservoir)
412+ case . failure( let error) :
413+ self . troubleshootPumpComms ( using: device)
414+ self . nightscoutDataManager. uploadLoopStatus ( loopError: error)
415+ nsPumpStatus = nil
403416 }
417+ self . nightscoutDataManager. uploadDeviceStatus ( nsPumpStatus)
404418 }
405419 }
406420
@@ -484,6 +498,65 @@ final class DeviceDataManager: CarbStoreDelegate, CarbStoreSyncDelegate, DoseSto
484498 }
485499 }
486500
501+ // MARK: - Enlite
502+
503+ fileprivate var latestEnliteData : EnliteSensorDisplayable ?
504+
505+ private func updateEnliteSensorStatus( _ events: [ TimestampedGlucoseEvent ] ) {
506+ let sensorEvents = events. filter ( { $0. glucoseEvent is RelativeTimestampedGlucoseEvent } )
507+
508+ if let latestSensorEvent = sensorEvents. last? . glucoseEvent as? RelativeTimestampedGlucoseEvent {
509+ self . latestEnliteData = EnliteSensorDisplayable ( latestSensorEvent)
510+ }
511+ }
512+
513+ private func assertCurrentEnliteData( ) {
514+ guard let device = rileyLinkManager. firstConnectedDevice, pumpDataIsStale ( ) else {
515+ return
516+ }
517+
518+ device. assertIdleListening ( )
519+
520+ let fetchGlucoseSince = glucoseStore? . latestGlucose? . startDate. addingTimeInterval ( TimeInterval ( minutes: 1 ) ) ?? Date ( timeIntervalSinceNow: TimeInterval ( hours: - 24 ) )
521+
522+ guard fetchGlucoseSince. timeIntervalSinceNow <= TimeInterval ( minutes: - 4.5 ) else {
523+ return
524+ }
525+
526+ device. ops? . getGlucoseHistoryEvents ( since: fetchGlucoseSince, completion: { ( result) in
527+ switch result {
528+ case . success( let glucoseEvents) :
529+
530+ defer {
531+ _ = self . remoteDataManager. nightscoutUploader? . processGlucoseEvents ( glucoseEvents, source: device. deviceURI)
532+ }
533+
534+ self . updateEnliteSensorStatus ( glucoseEvents)
535+
536+ let glucoseValues = glucoseEvents
537+ . filter ( { $0. glucoseEvent is SensorValueGlucoseEvent && $0. date > fetchGlucoseSince } )
538+ . map ( { ( e: TimestampedGlucoseEvent ) -> ( quantity: HKQuantity , date: Date , isDisplayOnly: Bool ) in
539+ let glucoseEvent = e. glucoseEvent as! SensorValueGlucoseEvent
540+ let quantity = HKQuantity ( unit: HKUnit . milligramsPerDeciliterUnit ( ) , doubleValue: Double ( glucoseEvent. sgv) )
541+ return ( quantity: quantity, date: e. date, isDisplayOnly: false )
542+ } )
543+
544+ self . glucoseStore? . addGlucoseValues ( glucoseValues, device: nil , resultHandler: { ( success, _, error) in
545+ if let error = error {
546+ self . logger. addError ( error, fromSource: " GlucoseStore " )
547+ }
548+
549+ if success {
550+ NotificationCenter . default. post ( name: . GlucoseUpdated, object: self )
551+ }
552+ } )
553+
554+ case . failure( let error) :
555+ self . logger. addError ( error, fromSource: " PumpOps " )
556+ }
557+ } )
558+ }
559+
487560 // MARK: - G5 Transmitter
488561 /// The G5 transmitter is a reliable heartbeat by which we can assert the loop state.
489562
0 commit comments