Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions Loop/Managers/LoopDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ final class LoopDataManager {
center.addObserver(forName: .CarbEntriesDidUpdate, object: nil, queue: nil) { (note) -> Void in
self.dataAccessQueue.async {
self.carbEffect = nil
self.carbsOnBoardSeries = nil
self.notify(forChange: .carbs)
}
}
Expand Down Expand Up @@ -165,6 +166,18 @@ final class LoopDataManager {
}
}

if carbsOnBoardSeries == nil, let carbStore = deviceDataManager.carbStore {
updateGroup.enter()
carbStore.getCarbsOnBoardValues { (values, error) in
if let error = error {
self.deviceDataManager.logger.addError(error, fromSource: "CarbStore")
}

self.carbsOnBoardSeries = values
updateGroup.leave()
}
}

if insulinEffect == nil {
updateGroup.enter()
updateInsulinEffect { (effects, error) in
Expand Down Expand Up @@ -229,9 +242,10 @@ final class LoopDataManager {
- lastTempBasal: The last set temp basal
- lastLoopCompleted: The last date at which a loop completed, from prediction to dose (if dosing is enabled)
- insulinOnBoard Current insulin on board
- carbsOnBoard Current carbs on board
- error: An error in the current state of the loop, or one that happened during the last attempt to loop.
*/
func getLoopStatus(_ resultsHandler: @escaping (_ predictedGlucose: [GlucoseValue]?, _ retrospectivePredictedGlucose: [GlucoseValue]?, _ recommendedTempBasal: TempBasalRecommendation?, _ lastTempBasal: DoseEntry?, _ lastLoopCompleted: Date?, _ insulinOnBoard: InsulinValue?, _ error: Error?) -> Void) {
func getLoopStatus(_ resultsHandler: @escaping (_ predictedGlucose: [GlucoseValue]?, _ retrospectivePredictedGlucose: [GlucoseValue]?, _ recommendedTempBasal: TempBasalRecommendation?, _ lastTempBasal: DoseEntry?, _ lastLoopCompleted: Date?, _ insulinOnBoard: InsulinValue?, _ carbsOnBoard: CarbValue?, _ error: Error?) -> Void) {
dataAccessQueue.async {
var error: Error?

Expand All @@ -241,7 +255,9 @@ final class LoopDataManager {
error = updateError
}

resultsHandler(self.predictedGlucose, self.retrospectivePredictedGlucose, self.recommendedTempBasal, self.lastTempBasal, self.lastLoopCompleted, self.insulinOnBoard, error ?? self.lastLoopError)
let currentCOB = self.carbsOnBoardSeries?.closestPriorToDate(Date())

resultsHandler(self.predictedGlucose, self.retrospectivePredictedGlucose, self.recommendedTempBasal, self.lastTempBasal, self.lastLoopCompleted, self.insulinOnBoard, currentCOB, error ?? self.lastLoopError)
}
}

Expand Down Expand Up @@ -294,6 +310,7 @@ final class LoopDataManager {
retrospectivePredictedGlucose = nil
}
}
private var carbsOnBoardSeries: [CarbValue]?
private var insulinEffect: [GlucoseEffect]? {
didSet {
if let bolusDate = lastBolus?.date, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) {
Expand Down Expand Up @@ -544,6 +561,7 @@ final class LoopDataManager {
self.dataAccessQueue.async {
if success {
self.carbEffect = nil
self.carbsOnBoardSeries = nil

do {
try self.update()
Expand Down Expand Up @@ -673,7 +691,7 @@ extension LoopDataManager {
///
/// - parameter completionHandler: A closure called once the report has been generated. The closure takes a single argument of the report string.
func generateDiagnosticReport(_ completionHandler: @escaping (_ report: String) -> Void) {
getLoopStatus { (predictedGlucose, retrospectivePredictedGlucose, recommendedTempBasal, lastTempBasal, lastLoopCompleted, insulinOnBoard, error) in
getLoopStatus { (predictedGlucose, retrospectivePredictedGlucose, recommendedTempBasal, lastTempBasal, lastLoopCompleted, insulinOnBoard, carbsOnBoard, error) in
let report = [
"## LoopDataManager",
"predictedGlucose: \(predictedGlucose ?? [])",
Expand All @@ -682,6 +700,7 @@ extension LoopDataManager {
"lastTempBasal: \(lastTempBasal)",
"lastLoopCompleted: \(lastLoopCompleted ?? .distantPast)",
"insulinOnBoard: \(insulinOnBoard)",
"carbsOnBoard: \(carbsOnBoard)",
"error: \(error)"
]
completionHandler(report.joined(separator: "\n"))
Expand Down
17 changes: 13 additions & 4 deletions Loop/Managers/NightscoutDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation
import NightscoutUploadKit
import CarbKit
import HealthKit
import InsulinKit
import LoopKit
Expand All @@ -34,20 +35,20 @@ class NightscoutDataManager {
return
}

deviceDataManager.loopManager.getLoopStatus { (predictedGlucose, _, recommendedTempBasal, lastTempBasal, _, insulinOnBoard, loopError) in
deviceDataManager.loopManager.getLoopStatus { (predictedGlucose, _, recommendedTempBasal, lastTempBasal, _, insulinOnBoard, carbsOnBoard, loopError) in

self.deviceDataManager.loopManager.getRecommendedBolus { (bolusUnits, getBolusError) in
if let getBolusError = getBolusError {
self.deviceDataManager.logger.addError(getBolusError, fromSource: "NightscoutDataManager")
}
self.uploadLoopStatus(insulinOnBoard, predictedGlucose: predictedGlucose, recommendedTempBasal: recommendedTempBasal, recommendedBolus: bolusUnits, lastTempBasal: lastTempBasal, loopError: loopError ?? getBolusError)
self.uploadLoopStatus(insulinOnBoard, carbsOnBoard: carbsOnBoard, predictedGlucose: predictedGlucose, recommendedTempBasal: recommendedTempBasal, recommendedBolus: bolusUnits, lastTempBasal: lastTempBasal, loopError: loopError ?? getBolusError)
}
}
}

private var lastTempBasalUploaded: DoseEntry?

func uploadLoopStatus(_ insulinOnBoard: InsulinValue? = nil, predictedGlucose: [GlucoseValue]? = nil, recommendedTempBasal: LoopDataManager.TempBasalRecommendation? = nil, recommendedBolus: Double? = nil, lastTempBasal: DoseEntry? = nil, loopError: Error? = nil) {
func uploadLoopStatus(_ insulinOnBoard: InsulinValue? = nil, carbsOnBoard: CarbValue? = nil, predictedGlucose: [GlucoseValue]? = nil, recommendedTempBasal: LoopDataManager.TempBasalRecommendation? = nil, recommendedBolus: Double? = nil, lastTempBasal: DoseEntry? = nil, loopError: Error? = nil) {

guard deviceDataManager.remoteDataManager.nightscoutUploader != nil else {
return
Expand All @@ -62,6 +63,14 @@ class NightscoutDataManager {
} else {
iob = nil
}

let cob: COBStatus?

if let carbsOnBoard = carbsOnBoard {
cob = COBStatus(cob: carbsOnBoard.quantity.doubleValue(for: HKUnit.gram()), timestamp: carbsOnBoard.startDate)
} else {
cob = nil
}

let predicted: PredictedBG?
if let predictedGlucose = predictedGlucose, let startDate = predictedGlucose.first?.startDate {
Expand Down Expand Up @@ -93,7 +102,7 @@ class NightscoutDataManager {
let loopName = Bundle.main.bundleDisplayName
let loopVersion = Bundle.main.shortVersionString

let loopStatus = LoopStatus(name: loopName, version: loopVersion, timestamp: statusTime, iob: iob, predicted: predicted, recommendedTempBasal: recommended, recommendedBolus: recommendedBolus, enacted: loopEnacted, failureReason: loopError)
let loopStatus = LoopStatus(name: loopName, version: loopVersion, timestamp: statusTime, iob: iob, cob: cob, predicted: predicted, recommendedTempBasal: recommended, recommendedBolus: recommendedBolus, enacted: loopEnacted, failureReason: loopError)

uploadDeviceStatus(nil, loopStatus: loopStatus, includeUploaderStatus: false)

Expand Down
2 changes: 1 addition & 1 deletion Loop/Managers/WatchDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ final class WatchDataManager: NSObject, WCSessionDelegate {
let reservoir = deviceDataManager.doseStore.lastReservoirValue
let maxBolus = deviceDataManager.maximumBolus

deviceDataManager.loopManager.getLoopStatus { (predictedGlucose, _, recommendedTempBasal, lastTempBasal, lastLoopCompleted, _, error) in
deviceDataManager.loopManager.getLoopStatus { (predictedGlucose, _, recommendedTempBasal, lastTempBasal, lastLoopCompleted, _, _, error) in
let eventualGlucose = predictedGlucose?.last

self.deviceDataManager.loopManager.getRecommendedBolus { (units, error) in
Expand Down
2 changes: 1 addition & 1 deletion Loop/View Controllers/PredictionTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class PredictionTableViewController: UITableViewController, IdentifiableClass, U
}

reloadGroup.enter()
self.dataManager.loopManager.getLoopStatus { (predictedGlucose, retrospectivePredictedGlucose, _, _, _, _, error) in
self.dataManager.loopManager.getLoopStatus { (predictedGlucose, retrospectivePredictedGlucose, _, _, _, _, _, error) in
if error != nil {
self.needsRefresh = true
}
Expand Down
2 changes: 1 addition & 1 deletion Loop/View Controllers/StatusTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ final class StatusTableViewController: UITableViewController, UIGestureRecognize
}

reloadGroup.enter()
self.dataManager.loopManager.getLoopStatus { (predictedGlucose, _, recommendedTempBasal, lastTempBasal, lastLoopCompleted, _, error) -> Void in
self.dataManager.loopManager.getLoopStatus { (predictedGlucose, _, recommendedTempBasal, lastTempBasal, lastLoopCompleted, _, _, error) -> Void in
if error != nil {
self.needsRefresh = true
}
Expand Down