|
|
@@ -145,41 +145,6 @@ extension MainViewController {
|
|
|
isDebug: true)
|
|
|
}
|
|
|
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Processing BG Data. Latest sensor reading: \(sensorTimestamp), now: \(now), secondsAgo: \(secondsAgo).",
|
|
|
- isDebug: true)
|
|
|
-
|
|
|
- // Check if we have a new reading (i.e. sensor timestamp is greater than what we last saw).
|
|
|
- if let lastTS = lastProcessedTimestamp {
|
|
|
- if sensorTimestamp > lastTS {
|
|
|
- if lastBgFetchMiss, let delay = lastBgFetchDelay {
|
|
|
- addObservedDelay(observedDelay: delay)
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Last attempt did not get any new data, storing the delay of \(delay) seconds.",
|
|
|
- isDebug: true)
|
|
|
- }
|
|
|
-
|
|
|
- lastBgFetchMiss = false
|
|
|
- lastProcessedTimestamp = sensorTimestamp
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "New reading detected. Sensor time: \(sensorTimestamp) updated (was \(lastTS)). Observed delay: \(secondsAgo) seconds.",
|
|
|
- isDebug: true)
|
|
|
- } else {
|
|
|
- lastBgFetchMiss = true
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "No new reading. Last processed sensor timestamp remains \(lastTS).",
|
|
|
- isDebug: true)
|
|
|
- }
|
|
|
- } else {
|
|
|
- lastProcessedTimestamp = sensorTimestamp
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "First reading processed. Sensor time: \(sensorTimestamp)",
|
|
|
- isDebug: true)
|
|
|
- }
|
|
|
-
|
|
|
- // Compute a typical delay from our historical data.
|
|
|
- let typicalDelay = computeOptimalDelay()
|
|
|
-
|
|
|
// Determine the next polling delay.
|
|
|
var delayToSchedule: Double = 0
|
|
|
|
|
|
@@ -203,43 +168,15 @@ extension MainViewController {
|
|
|
} else if secondsAgo >= (5 * 60) {
|
|
|
delayToSchedule = 5
|
|
|
LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Reading is clost to 5 minutes old (\(secondsAgo) sec). Scheduling next fetch in 10 seconds.",
|
|
|
+ message: "Reading is close to 5 minutes old (\(secondsAgo) sec). Scheduling next fetch in 5 seconds.",
|
|
|
isDebug: true)
|
|
|
} else {
|
|
|
- // For fresh readings, predict when the next reading should appear.
|
|
|
- // The sensor is scheduled to take a measurement every 300 seconds.
|
|
|
- // Our base delay is: time remaining until 5 minutes from sensor timestamp + typical delay.
|
|
|
- let baseDelay = 300 - secondsAgo + typicalDelay
|
|
|
- delayToSchedule = baseDelay
|
|
|
+ delayToSchedule = 300 - secondsAgo + Double(UserDefaultsRepository.bgUpdateDelay.value)
|
|
|
LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Fresh reading. Base delay computed as: 300 - \(secondsAgo) + \(typicalDelay) = \(baseDelay) seconds.",
|
|
|
+ message: "Fresh reading. Scheduling next fetch in \(delayToSchedule) seconds.",
|
|
|
isDebug: true)
|
|
|
-
|
|
|
- // Exploration: occasionally try polling earlier than expected.
|
|
|
- let explorationRoll = Double.random(in: 0..<1)
|
|
|
- // Chance (0.0–1.0) to try an earlier poll than predicted.
|
|
|
- let explorationProbability: Double = 0.2
|
|
|
-
|
|
|
- if explorationRoll < explorationProbability {
|
|
|
- // The absolute minimum delay we allow.
|
|
|
- let minDelay: Double = 3.0
|
|
|
-
|
|
|
- // How many seconds to subtract when doing an exploratory poll.
|
|
|
- let explorationOffset: Double = 1
|
|
|
-
|
|
|
- let exploredDelay = max(minDelay, baseDelay - explorationOffset)
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Exploration triggered. Adjusting delay from \(baseDelay) to \(exploredDelay) seconds.",
|
|
|
- isDebug: true)
|
|
|
- delayToSchedule = exploredDelay
|
|
|
- }
|
|
|
}
|
|
|
- self.lastBgFetchDelay = secondsAgo - delayToSchedule
|
|
|
|
|
|
- // Log and schedule the next fetch.
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Scheduling next BG fetch in \(delayToSchedule) seconds (at \(Date().addingTimeInterval(delayToSchedule))).",
|
|
|
- isDebug: true)
|
|
|
TaskScheduler.shared.rescheduleTask(id: .fetchBG, to: Date().addingTimeInterval(delayToSchedule))
|
|
|
|
|
|
// Evaluate speak conditions if there is a previous value.
|
|
|
@@ -288,44 +225,6 @@ extension MainViewController {
|
|
|
return secondsSinceStartOfDay.truncatingRemainder(dividingBy: 300)
|
|
|
}
|
|
|
|
|
|
- private func computeOptimalDelay() -> Double {
|
|
|
- if Storage.shared.bgDelayDynamicEnabled.value {
|
|
|
- guard let optimal = observedDelays.min() else {
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "No previous observed delays, starting with \(Storage.shared.bgDelayDynamicDelay.value) seconds.",
|
|
|
- isDebug: true)
|
|
|
- return Storage.shared.bgDelayDynamicDelay.value
|
|
|
- }
|
|
|
- Storage.shared.bgDelayDynamicDelay.value = optimal
|
|
|
-
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Computed optimal delay from observations \(observedDelays) is \(optimal) seconds.",
|
|
|
- isDebug: true)
|
|
|
- return optimal
|
|
|
- } else {
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Dynamic bg delay is disabled, using user set value of \(UserDefaultsRepository.bgUpdateDelay.value) seconds.",
|
|
|
- isDebug: true)
|
|
|
- return Double(UserDefaultsRepository.bgUpdateDelay.value)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private func addObservedDelay(observedDelay : Double) {
|
|
|
- guard observedDelay > 3, observedDelay < 45 else {
|
|
|
- LogManager.shared.log(category: .nightscout,
|
|
|
- message: "Observed delay of \(observedDelay) seconds is out of range, ignored.",
|
|
|
- isDebug: true)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- observedDelays.append(observedDelay)
|
|
|
-
|
|
|
- // Keep delays for the last hour
|
|
|
- if observedDelays.count > 12 {
|
|
|
- observedDelays.removeFirst()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
func updateServerText(with serverText: String? = nil) {
|
|
|
if UserDefaultsRepository.showDisplayName.value, let displayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
|
|
|
self.serverText.text = displayName
|