Skip to content

Commit 9e43be4

Browse files
authored
Merge pull request #375 from loopandlearn/estimated-delay
Estimated bg delay
2 parents 6382e24 + 688233c commit 9e43be4

File tree

9 files changed

+218
-67
lines changed

9 files changed

+218
-67
lines changed

LoopFollow.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
DD608A0A2C23593900F91132 /* SMB.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD608A092C23593900F91132 /* SMB.swift */; };
7171
DD608A0C2C27415C00F91132 /* BackgroundAlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD608A0B2C27415C00F91132 /* BackgroundAlertManager.swift */; };
7272
DD6A935E2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A935D2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift */; };
73+
DD7B0D442D730A3B0063DCB6 /* CycleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7B0D432D730A320063DCB6 /* CycleHelper.swift */; };
7374
DD7E19842ACDA50C00DBD158 /* Overrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19832ACDA50C00DBD158 /* Overrides.swift */; };
7475
DD7E19862ACDA59700DBD158 /* BGCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19852ACDA59700DBD158 /* BGCheck.swift */; };
7576
DD7E19882ACDA5DA00DBD158 /* Notes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19872ACDA5DA00DBD158 /* Notes.swift */; };
@@ -347,6 +348,7 @@
347348
DD608A092C23593900F91132 /* SMB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMB.swift; sourceTree = "<group>"; };
348349
DD608A0B2C27415C00F91132 /* BackgroundAlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundAlertManager.swift; sourceTree = "<group>"; };
349350
DD6A935D2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStatusOpenAPS.swift; sourceTree = "<group>"; };
351+
DD7B0D432D730A320063DCB6 /* CycleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CycleHelper.swift; sourceTree = "<group>"; };
350352
DD7E19832ACDA50C00DBD158 /* Overrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Overrides.swift; sourceTree = "<group>"; };
351353
DD7E19852ACDA59700DBD158 /* BGCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGCheck.swift; sourceTree = "<group>"; };
352354
DD7E19872ACDA5DA00DBD158 /* Notes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notes.swift; sourceTree = "<group>"; };
@@ -1107,6 +1109,7 @@
11071109
FCC688542489367300A0279D /* Helpers */ = {
11081110
isa = PBXGroup;
11091111
children = (
1112+
DD7B0D432D730A320063DCB6 /* CycleHelper.swift */,
11101113
DDF6999C2C5AAA4C0058A8D9 /* Views */,
11111114
FCC6886E2489A53800A0279D /* AppConstants.swift */,
11121115
FCC6886A24898FD800A0279D /* ObservationToken.swift */,
@@ -1459,6 +1462,7 @@
14591462
DD4878172C7B75350048F05C /* BolusView.swift in Sources */,
14601463
DD493AE72ACF23CF009A6922 /* DeviceStatus.swift in Sources */,
14611464
FCFEECA2248857A600402A7F /* SettingsViewController.swift in Sources */,
1465+
DD7B0D442D730A3B0063DCB6 /* CycleHelper.swift in Sources */,
14621466
DD9ACA0C2D33BB8600415D8A /* CalendarTask.swift in Sources */,
14631467
DD13BC792C3FE63A0062313B /* InfoManager.swift in Sources */,
14641468
DD0C0C702C4AFFE800DBADDF /* RemoteViewController.swift in Sources */,

LoopFollow/BackgroundRefresh/BT/BLEDeviceSelectionView.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,27 @@ struct BLEDeviceSelectionView: View {
1313
var body: some View {
1414
VStack {
1515
List {
16-
if bleManager.devices.filter({ selectedFilter.matches($0) && !isSelected($0) }).isEmpty {
16+
let filteredDevices = bleManager.devices.filter { selectedFilter.matches($0) && !isSelected($0) }
17+
if filteredDevices.isEmpty {
1718
Text("No devices found yet. They'll appear here when discovered.")
1819
.foregroundColor(.secondary)
1920
.multilineTextAlignment(.center)
2021
.padding()
2122
} else {
22-
ForEach(bleManager.devices.filter { selectedFilter.matches($0) && !isSelected($0) }, id: \.id) { device in
23+
ForEach(filteredDevices, id: \.id) { device in
2324
HStack {
2425
VStack(alignment: .leading) {
2526
Text(device.name ?? "Unknown")
2627

2728
Text("RSSI: \(device.rssi) dBm")
2829
.foregroundColor(.secondary)
2930
.font(.footnote)
31+
32+
if let offset = BLEManager.shared.expectedSensorFetchOffsetString(for: device) {
33+
Text("Expected bg delay: \(offset)")
34+
.foregroundColor(.secondary)
35+
.font(.footnote)
36+
}
3037
}
3138
Spacer()
3239
}

LoopFollow/BackgroundRefresh/BT/BLEManager.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,42 @@ extension BLEManager: BluetoothDeviceDelegate {
213213
TaskScheduler.shared.checkTasksNow()
214214
}
215215
}
216+
217+
extension BLEManager {
218+
/// Returns the expected sensor fetch offset as a formatted string ("mm:ss (fetch delay: XX sec)")
219+
/// for Dexcom and RileyLink devices. The expected offset is computed as the sensor's schedule offset plus the polling delay.
220+
/// The device’s lastSeen time is used (mod cycleDuration) to calculate the effective delay between when the sensor value
221+
/// becomes available and when the fetch is actually triggered.
222+
func expectedSensorFetchOffsetString(for device: BLEDevice) -> String? {
223+
guard
224+
let matchedType = BackgroundRefreshType.allCases.first(where: { $0.matches(device) }),
225+
let heartBeatInterval = matchedType.heartBeatInterval,
226+
let sensorOffset = Storage.shared.sensorScheduleOffset.value
227+
else {
228+
return nil
229+
}
230+
231+
let heartbeatLast: Date? = {
232+
if matchedType.estimatedDelayBasedOnHeartbeat {
233+
guard device.isConnected, let lastHeartbeat = activeDevice?.lastHeartbeatTime else {
234+
return nil
235+
}
236+
return lastHeartbeat
237+
} else {
238+
return device.lastSeen
239+
}
240+
}()
241+
242+
guard let heartbeatLast = heartbeatLast else {
243+
return nil
244+
}
245+
246+
let pollingDelay: TimeInterval = Double(UserDefaultsRepository.bgUpdateDelay.value)
247+
248+
let expectedOffset = sensorOffset + pollingDelay
249+
250+
let effectiveDelay = CycleHelper.computeDelay(sensorOffset: expectedOffset, heartbeatLast: heartbeatLast, heartbeatInterval: heartBeatInterval)
251+
252+
return "\(Int(effectiveDelay)) sec"
253+
}
254+
}

LoopFollow/BackgroundRefresh/BT/Devices/RileyLinkHeartbeatBluetoothDevice.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class RileyLinkHeartbeatBluetoothDevice: BluetoothDevice {
2727

2828
override func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
2929
super.centralManager(central, didConnect: peripheral)
30-
31-
self.bluetoothDeviceDelegate?.heartBeat()
3230
}
3331

3432
override func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

LoopFollow/BackgroundRefresh/BackgroundRefreshSettingsView.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ struct BackgroundRefreshSettingsView: View {
7373
.foregroundColor(.secondary)
7474

7575
case .dexcom:
76-
Text("Requires a Dexcom G6/ONE/G7/ONE+ transmitter within Bluetooth range. Provides updates every 5 minutes and uses less battery than the silent tune method.")
76+
Text("Requires a Dexcom G6/ONE/G7/ONE+ transmitter within Bluetooth range. Provides updates every 5 minutes and uses less battery than the silent tune method. If you have more than one device to choose from, select the one with the smallest expected bg delay.")
7777
.font(.footnote)
7878
.foregroundColor(.secondary)
7979
}
@@ -97,6 +97,11 @@ struct BackgroundRefreshSettingsView: View {
9797
.foregroundColor(.secondary)
9898
.font(.footnote)
9999
}
100+
if let offset = BLEManager.shared.expectedSensorFetchOffsetString(for: storedDevice) {
101+
Text("Expected bg delay: \(offset)")
102+
.foregroundColor(.secondary)
103+
.font(.footnote)
104+
}
100105

101106
HStack {
102107
Spacer()

LoopFollow/BackgroundRefresh/BackgroundRefreshType.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,26 @@ enum BackgroundRefreshType: String, Codable, CaseIterable {
2323
}
2424
}
2525

26+
var heartBeatInterval: TimeInterval? {
27+
switch self {
28+
case .rileyLink:
29+
return 60
30+
case .dexcom:
31+
return 5 * 60
32+
case .silentTune, .none:
33+
return nil
34+
}
35+
}
36+
37+
var estimatedDelayBasedOnHeartbeat: Bool {
38+
switch self {
39+
case .rileyLink:
40+
return true
41+
case .dexcom, .silentTune, .none:
42+
return false
43+
}
44+
}
45+
2646
/// Determines if a BLEDevice matches the specific device type
2747
func matches(_ device: BLEDevice) -> Bool {
2848
switch self {

0 commit comments

Comments
 (0)