Debounce alarm checks and improve scheduling logic by bjorkert · Pull Request #432 · loopandlearn/LoopFollow
Summary
This pull request resolves an issue where alarmCheck was being executed excessively in rapid succession when multiple data sources refreshed simultaneously. It refactors the task scheduling logic to be more efficient and reliable by debouncing the calls.
Changes
-
Debounced
alarmCheckCalls:- In
BGData.swift,DeviceStatus.swift, andTreatmentsTask.swift, the call to reschedulealarmCheckis now delayed by 3 seconds (.addingTimeInterval(3)). - This ensures that if multiple data refreshes occur in a short window,
alarmCheckonly runs once after the final update, preventing redundant executions.
- In
-
Simplified
TaskScheduler:- The previous complex logic to manually skip
alarmCheckhas been removed fromTaskScheduler.swift. - This logic is now obsolete due to the debouncing mechanism and its removal simplifies the scheduler's code.
- The previous complex logic to manually skip
-
Improved
RecBolusCondition:- The condition now triggers if the recommended bolus is the same as or greater than the last notified value (changed from strictly greater than).
- This makes the alarm more stable and prevents it from stopping if a check runs with the same value that triggered it.
-
Added Debug Logging:
- A new debug log was added to
AlarmManagerto clearly indicate when an alarm is being stopped because its conditions are no longer met.
- A new debug log was added to
Result
These changes lead to a more robust, predictable, and efficient alarm system with cleaner, more maintainable code.
Repeating here what I sent in private message.
Logic modification requested
This is the scenario where I think we need an additional modification.
I am assuming that you expect an alert in step 3.
- rec bolus (8) > threshold (2) - get alert
- rec bolus decreases over time but stays above 2 (so not set back to nil) - no alert
- rec bolus increases (any amount up to and including 8)
- Without updating Storage.shared.lastRecBolusNotified.value each time, you will not be alerted at event 3.
Suggested code change for RecBolusCondition.swift:
diff --git a/LoopFollow/Alarm/AlarmCondition/RecBolusCondition.swift b/LoopFollow/Alarm/AlarmCondition/RecBolusCondition.swift
index db0f58d..185f669 100644
--- a/LoopFollow/Alarm/AlarmCondition/RecBolusCondition.swift
+++ b/LoopFollow/Alarm/AlarmCondition/RecBolusCondition.swift
@@ -20,9 +20,11 @@ struct RecBolusCondition: AlarmCondition {
}
// ────────────────────────────────
- // 1. has it INCREASED past the last-notified value?
+ // 1. No alert if no increase from last-notified value
+ // 2. update stored value to alert for an increase
// ────────────────────────────────
if let last = Storage.shared.lastRecBolusNotified.value {
+ Storage.shared.lastRecBolusNotified.value = rec
if rec <= last + 1e-4 { return false }
}
Testing - Trio URL
I tested this modification. With an alert at 1 U rec bolus
Initial build is dev
- alerted at 2.44 U
- not alerted at 2.07 U
- not alerted at 1.19 U
- deleted last 3 SMB of 0.5 U each so I can stay above 1 U rec bolus
- added more carbs to increase rec bolus
- rec bolus increased to 1.67 U, no alert (dev build) << why I request the logic change
- rec bolus increased to 2.07 U, no alert (dev build)
build modified debounce-alarm-checks
- rec bolus increased to 2.18 U and got an alert << I think this is correct behavior
- rec bolus decreased to 1.95 U and no alert << do not want an alert here, so success
- rec bolus increased to 2.10 U no alert
- not sure why this did not alert, but the timing for the alert for Trio is strange (to me) and I was going in and deleting SMB to keep value of rec bolus up
- rec bolus decreased to 1.92 U no alert
- rec bolus increased to 2.2 and get alert
I will repeat this test with Loop in the next comment.
Test summary with modification applied
When rec bolus increases, you get an alert if above threshold.
When rec bolus is stable or decreasing, the alert is not repeated.
Do we need a scenario to handle slight increase?
In other words:
// do not alert for slight increases in rec bolus
if rec <= last * (1.05) { return false }
Testing with Loop URL
build modified debounce-alarm-checks
- observe Loop URL (I understand Loop rec bolus better)
- set to Temp Basal only with low max basal rate
- add carbs but do not bolus
- ALERT SUCCESS: initial alert for rec bolus comes with amount of 2.4 U and got an alert
- next rec bolus is 2.25, no alert
- walked away for a while, rec bolus is 1.1 U
- ALERT SUCCESS: add more carbs, rec bolus is 2.85 and got an alert
- let it decay for a couple of cycles and make sure no alerts happen
- rec bolus 2.65, no alarm
- rec bolus 2.65, no alarm
- ALERT SUCCESS: add more carbs, rec bolus is 4.70 and got an alert
- ALERT SUCCESS: glucose increased, rec bolus is 4.90 and got an alert
Summary of Changes
The latest commit addresses the recommended bolus alert logic to ensure users get notified appropriately when bolus recommendations increase, while avoiding excessive alerts for minor fluctuations.
Key Changes Made:
-
Always update the stored value:
Storage.shared.lastRecBolusNotified.value = recis now called every time the rec bolus is above threshold, ensuring the system tracks the current recommendation level. -
5% increase threshold: Replaced the previous
1e-4tolerance with a 5% increase requirement:shouldAlert = rec > last * (1.05). This means you only get alerted when the rec bolus increases by more than 5% from the last notification. -
Cleaner logic flow: The code now clearly separates threshold checking from increase detection, making the logic more readable and maintainable.
How This Works - Examples:
Scenario 1: Initial Alert and 5% Increase Rule
- Rec bolus reaches 3.0 U (above 2.0 U threshold) → Alert triggered ✅ (first time above threshold)
- Rec bolus stays at 3.0 U → No alert (no increase, stored value updated to 3.0)
- Rec bolus increases to 3.1 U → No alert (only 3.3% increase from stored 3.0 U, stored value updated to 3.1)
- Rec bolus increases to 3.2 U → No alert (only 3.2% increase from stored 3.1 U, stored value updated to 3.2)
- Rec bolus increases to 3.4 U → Alert triggered ✅ (6.25% increase from stored 3.2 U)
Scenario 2: After Decay and Recovery
- Rec bolus at 4.0 U → Alert triggered ✅ (assuming first time or >5% increase)
- Rec bolus decreases to 2.5 U → No alert (decrease, stored value updated to 2.5)
- Rec bolus decreases to 1.8 U → No alert (below threshold, stored value reset to nil)
- Rec bolus increases to 2.5 U → Alert triggered ✅ (first time above threshold after reset)
Scenario 3: Preventing Minor Fluctuation Spam
- Rec bolus at 2.0 U → Alert triggered ✅ (first time above threshold, stored as 2.0)
- Rec bolus fluctuates to 2.05 U → No alert (2.5% increase from 2.0, stored as 2.05)
- Rec bolus fluctuates to 2.03 U → No alert (decrease from 2.05, stored as 2.03)
- Rec bolus jumps to 2.15 U → Alert triggered ✅ (5.9% increase from stored 2.03)
Benefits:
- Smart threshold: 5% increase requirement prevents alerts for minor fluctuations while catching meaningful changes
- Responsive to significant changes: Users get alerted when rec bolus meaningfully increases, not just any tiny change
- Automatic reset: When rec bolus goes below threshold, the stored value resets to nil, so the next time it goes above threshold triggers an alert
- Intuitive behavior: Balances being responsive to important changes while avoiding notification spam
Test Summary
Test successful
Test
Spot check because this code is effectively the same (although cleaner design) as what I tested before.
Use a Loop URL as the source for LoopFollow
Alarm is set for Rec Bolus of 1 U
Begin with a rec bolus of 3.65 U showing on the Loop URL (LoopFollow alerted when I first opened it)
- ✅ Next Rec Bolus is less, no alert sounds
- Modify Loop settings to decrease Rec Bolus below threshold
- Rec Bolus now < 1 U (should reset the alert)
- Add carbs on Loop phone to push Rec Bolus > 1 U
- ✅ alert sounds for Rec Bolus of 1.55 U
- leave Loop phone alone for 10 minutes to make sure alert does not repeat
- final Rec Bolus is 1.1 U
- Add carbs on Loop phone to push Rec Bolus higher by large amount (> 5% increase)
- ✅ alert sounds for Rec Bolus of 6.15 U
- Add carbs on Loop phone to push Rec Bolus higher by small amount (< 5%)
- ✅ alert does not sound for Rec Bolus of 6.30 U (3% increase)
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved from code review and test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters