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
24 changes: 24 additions & 0 deletions LoopFollow/Controllers/Graphs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,30 @@ extension MainViewController {
BGChart.notifyDataSetChanged()
}

// Removes the Loop forecast line. Used when the active system switches away from Loop.
func clearLoopPredictionGraph() {
guard !predictionData.isEmpty else { return }
predictionData.removeAll()
updatePredictionGraph()
}

// Removes the Trio/OpenAPS forecast lines (ZT/IOB/COB/UAM). Used when the active system switches away from Trio/OpenAPS.
func clearOpenAPSPredictionGraph() {
let openAPSDataIndices = [12, 13, 14, 15]
for dataIndex in openAPSDataIndices {
let mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
let smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
if !mainChart.entries.isEmpty || !smallChart.entries.isEmpty {
updatePredictionGraphGeneric(
dataIndex: dataIndex,
predictionData: [],
chartLabel: "",
color: UIColor.systemGray
)
}
}
}

func updatePredictionGraph(color: UIColor? = nil) {
let dataIndex = 1
var mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
Expand Down
23 changes: 23 additions & 0 deletions LoopFollow/Controllers/Nightscout/DeviceStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ extension MainViewController {
// NS Device Status Response Processor
func updateDeviceStatusDisplay(jsonDeviceStatus: [[String: AnyObject]]) {
let previousIOBText = Observable.shared.iobText.value
let previousDeviceWasLoop = Storage.shared.device.value == "Loop"
infoManager.clearInfoData(types: [.iob, .cob, .battery, .pump, .pumpBattery, .target, .isf, .carbRatio, .updated, .recBolus, .tdd])

// For Loop, clear the current override here - For Trio, it is handled using treatments
Expand Down Expand Up @@ -155,6 +156,17 @@ extension MainViewController {

// Loop - handle new data
if let lastLoopRecord = lastDeviceStatus?["loop"] as! [String: AnyObject]? {
// Some pumps report no `pump.clock`; without it alertLastLoopTime stays 0
// and the forecast anchors to epoch 0. Fall back to the loop cycle timestamp.
if (lastDeviceStatus?["pump"] as? [String: AnyObject])?["clock"] == nil,
let loopTimestampString = lastLoopRecord["timestamp"] as? String,
let loopTimestamp = formatter.date(from: loopTimestampString)?.timeIntervalSince1970,
loopTimestamp > (Observable.shared.alertLastLoopTime.value ?? 0)
{
Observable.shared.alertLastLoopTime.value = loopTimestamp
Storage.shared.lastLoopTime.value = loopTimestamp
}

DeviceStatusLoop(formatter: formatter, lastLoopRecord: lastLoopRecord)

var oText = ""
Expand Down Expand Up @@ -188,6 +200,17 @@ extension MainViewController {
DeviceStatusOpenAPS(formatter: formatter, lastDeviceStatus: lastDeviceStatus, lastLoopRecord: lastLoopRecord)
}

// If the active looping system flipped (Loop ⇄ Trio/OpenAPS), drop the previous
// system's forecast so it doesn't linger next to the one just drawn above.
let currentDeviceIsLoop = Storage.shared.device.value == "Loop"
if currentDeviceIsLoop != previousDeviceWasLoop {
if currentDeviceIsLoop {
clearOpenAPSPredictionGraph()
} else {
clearLoopPredictionGraph()
}
}

// Start the timer based on the timestamp
let now = dateTimeUtils.getNowTimeIntervalUTC()
let secondsAgo = now - (Observable.shared.alertLastLoopTime.value ?? 0)
Expand Down
2 changes: 1 addition & 1 deletion LoopFollow/Controllers/Nightscout/DeviceStatusLoop.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ extension MainViewController {
let prediction = predictdata["values"] as! [Double]
Observable.shared.predictionText.value = Localizer.toDisplayUnits(String(Int(round(prediction.last!))))
Observable.shared.predictionColor.value = .purple
if Storage.shared.downloadPrediction.value, previousLastLoopTime < lastLoopTime {
if Storage.shared.downloadPrediction.value, previousLastLoopTime < lastLoopTime || predictionData.isEmpty {
predictionData.removeAll()
var predictionTime = lastLoopTime
let toLoad = Int(Storage.shared.predictionToLoad.value * 12)
Expand Down
4 changes: 4 additions & 0 deletions LoopFollow/Task/DeviceStatusTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ extension MainViewController {
func deviceStatusAction() {
// If no NS config, we wait 60s before trying again:
guard IsNightscoutEnabled() else {
// No device-status source (e.g. Dexcom-only): drop any forecast left over
// from a previous Loop/Trio source so it doesn't linger on the chart.
clearLoopPredictionGraph()
clearOpenAPSPredictionGraph()
TaskScheduler.shared.rescheduleTask(id: .deviceStatus, to: Date().addingTimeInterval(60))
return
}
Expand Down
23 changes: 0 additions & 23 deletions LoopFollow/ViewControllers/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -565,29 +565,6 @@ class MainViewController: UIViewController, ChartViewDelegate, UNUserNotificatio
@objc func refresh() {
LogManager.shared.log(category: .general, message: "Refreshing")

// Clear prediction for both Loop or OpenAPS

// Check if Loop prediction data exists and clear it if necessary
if !predictionData.isEmpty {
predictionData.removeAll()
updatePredictionGraph()
}

// Check if OpenAPS prediction data exists and clear it if necessary
let openAPSDataIndices = [12, 13, 14, 15]
for dataIndex in openAPSDataIndices {
let mainChart = BGChart.lineData!.dataSets[dataIndex] as! LineChartDataSet
let smallChart = BGChartFull.lineData!.dataSets[dataIndex] as! LineChartDataSet
if !mainChart.entries.isEmpty || !smallChart.entries.isEmpty {
updatePredictionGraphGeneric(
dataIndex: dataIndex,
predictionData: [],
chartLabel: "",
color: UIColor.systemGray
)
}
}

Observable.shared.minAgoText.value = "Refreshing"
scheduleAllTasks()
NightscoutSocketManager.shared.connectIfNeeded()
Expand Down
Loading