Skip to content

Commit

Permalink
Merge pull request #291 from loopandlearn/recommended-bolus-alert
Browse files Browse the repository at this point in the history
Add recommended bolus alert
  • Loading branch information
marionbarker committed May 6, 2024
2 parents 9e2d446 + f28a7b4 commit 27226de
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 64 deletions.
23 changes: 21 additions & 2 deletions LoopFollow/Controllers/Alarms.swift
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,21 @@ extension MainViewController {
}
}

if UserDefaultsRepository.alertRecBolusActive.value && !UserDefaultsRepository.alertRecBolusIsSnoozed.value {
let currentRecBolus = UserDefaultsRepository.deviceRecBolus.value
let alertAtRecBolus = Double(UserDefaultsRepository.alertRecBolusLevel.value)

if currentRecBolus >= alertAtRecBolus {
AlarmSound.whichAlarm = "Rec. Bolus"

if UserDefaultsRepository.alertRecBolusRepeat.value { numLoops = -1 }
triggerAlarm(sound: UserDefaultsRepository.alertRecBolusSound.value, snooozedBGReadingTime: nil, overrideVolume: UserDefaultsRepository.overrideSystemOutputVolume.value, numLoops: numLoops, snoozeTime: UserDefaultsRepository.alertRecBolusSnooze.value, snoozeIncrement: 5, audio: true)
return
}
}

// still send persistent notification if no alarms trigger and persistent notification is on
persistentNotification(bgTime: currentBGTime)

}

func checkOverrideAlarms()
Expand Down Expand Up @@ -773,7 +785,14 @@ extension MainViewController {
alarms.reloadSnoozeTime(key: "alertBatterySnoozedTime", setNil: true)
alarms.reloadIsSnoozed(key: "alertBatteryIsSnoozed", value: false)
}
}

if date > UserDefaultsRepository.alertRecBolusSnoozedTime.value ?? date {
UserDefaultsRepository.alertRecBolusSnoozedTime.setNil(key: "alertRecBolusSnoozedTime")
UserDefaultsRepository.alertRecBolusIsSnoozed.value = false
alarms.reloadSnoozeTime(key: "alertRecBolusSnoozedTime", setNil: true)
alarms.reloadIsSnoozed(key: "alertRecBolusIsSnoozed", value: false)
}
}

func checkQuietHours() {
if UserDefaultsRepository.quietHourStart.value == nil || UserDefaultsRepository.quietHourEnd.value == nil { return }
Expand Down
12 changes: 10 additions & 2 deletions LoopFollow/Controllers/Nightscout/DeviceStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ extension MainViewController {
}
if let recBolus = lastLoopRecord["recommendedBolus"] as? Double {
tableData[8].value = String(format:"%.2fU", recBolus)
UserDefaultsRepository.deviceRecBolus.value = recBolus
}
if let loopStatus = lastLoopRecord["recommendedTempBasal"] as? [String:AnyObject] {
if let tempBasalTime = formatter.date(from: (loopStatus["timestamp"] as! String))?.timeIntervalSince1970 {
Expand Down Expand Up @@ -239,9 +240,16 @@ extension MainViewController {
tableData[1].value = String(format:"%.0f", cobdata["COB"] as! Double)
latestCOB = String(format:"%.0f", cobdata["COB"] as! Double)
}
if let recbolusdata = lastLoopRecord["enacted"] as? [String:AnyObject] {
tableData[8].value = String(format:"%.2fU", recbolusdata["insulinReq"] as! Double)
if let recbolusdata = lastLoopRecord["enacted"] as? [String: AnyObject],
let insulinReq = recbolusdata["insulinReq"] as? Double {
tableData[8].value = String(format: "%.2fU", insulinReq)
UserDefaultsRepository.deviceRecBolus.value = insulinReq
} else {
tableData[8].value = "N/A"
UserDefaultsRepository.deviceRecBolus.value = 0
print("Warning: Failed to extract insulinReq from recbolusdata.")
}

if let autosensdata = lastLoopRecord["enacted"] as? [String:AnyObject] {
let sens = autosensdata["sensitivityRatio"] as! Double * 100.0
tableData[11].value = String(format:"%.0f", sens) + "%"
Expand Down
114 changes: 106 additions & 8 deletions LoopFollow/ViewControllers/AlarmViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ class AlarmViewController: FormViewController {
<<< SegmentedRow<String>("bgAlerts"){ row in
row.title = ""
row.options = ["Urgent Low", "Low", "High", "Urgent High"]
// row.value = "Urgent Low"
}.onChange { [weak self] row in
guard let value = row.value else { return }
let otherRow = self?.form.rowBy(tag: "bgExtraAlerts") as! SegmentedRow<String>
Expand All @@ -267,12 +266,14 @@ class AlarmViewController: FormViewController {
let otherRow4 = self?.form.rowBy(tag: "otherAlerts3") as! SegmentedRow<String>
otherRow4.value = nil
otherRow4.reload()
let otherRow5 = self?.form.rowBy(tag: "otherAlerts4") as! SegmentedRow<String>
otherRow5.value = nil
otherRow5.reload()
row.value = value
}
<<< SegmentedRow<String>("bgExtraAlerts"){ row in
row.title = ""
row.options = ["No Readings", "Fast Drop", "Fast Rise", "Temporary"]
//row.value = "Missed Readings"
}.onChange { [weak self] row in
guard let value = row.value else { return }
let otherRow = self?.form.rowBy(tag: "bgAlerts") as! SegmentedRow<String>
Expand All @@ -287,6 +288,9 @@ class AlarmViewController: FormViewController {
let otherRow4 = self?.form.rowBy(tag: "otherAlerts3") as! SegmentedRow<String>
otherRow4.value = nil
otherRow4.reload()
let otherRow5 = self?.form.rowBy(tag: "otherAlerts4") as! SegmentedRow<String>
otherRow5.value = nil
otherRow5.reload()
row.value = value
}
<<< SegmentedRow<String>("otherAlerts"){ row in
Expand All @@ -295,8 +299,6 @@ class AlarmViewController: FormViewController {
if UserDefaultsRepository.url.value == "" {
row.hidden = true
}

//row.value = "Not Looping"
}.onChange { [weak self] row in
guard let value = row.value else { return }
let otherRow = self?.form.rowBy(tag: "bgExtraAlerts") as! SegmentedRow<String>
Expand All @@ -311,6 +313,9 @@ class AlarmViewController: FormViewController {
let otherRow4 = self?.form.rowBy(tag: "otherAlerts3") as! SegmentedRow<String>
otherRow4.value = nil
otherRow4.reload()
let otherRow5 = self?.form.rowBy(tag: "otherAlerts4") as! SegmentedRow<String>
otherRow5.value = nil
otherRow5.reload()
row.value = value
}
<<< SegmentedRow<String>("otherAlerts2"){ row in
Expand All @@ -319,7 +324,6 @@ class AlarmViewController: FormViewController {
if UserDefaultsRepository.url.value == "" {
row.hidden = true
}
//row.value = "Not Looping"
}.onChange { [weak self] row in
guard let value = row.value else { return }
let otherRow = self?.form.rowBy(tag: "bgExtraAlerts") as! SegmentedRow<String>
Expand All @@ -334,6 +338,9 @@ class AlarmViewController: FormViewController {
let otherRow4 = self?.form.rowBy(tag: "otherAlerts3") as! SegmentedRow<String>
otherRow4.value = nil
otherRow4.reload()
let otherRow5 = self?.form.rowBy(tag: "otherAlerts4") as! SegmentedRow<String>
otherRow5.value = nil
otherRow5.reload()
row.value = value
}

Expand All @@ -343,7 +350,6 @@ class AlarmViewController: FormViewController {
if UserDefaultsRepository.url.value == "" {
row.hidden = true
}
//row.value = "Not Looping"
}.onChange { [weak self] row in
guard let value = row.value else { return }
let otherRow = self?.form.rowBy(tag: "bgExtraAlerts") as! SegmentedRow<String>
Expand All @@ -358,10 +364,37 @@ class AlarmViewController: FormViewController {
let otherRow4 = self?.form.rowBy(tag: "otherAlerts2") as! SegmentedRow<String>
otherRow4.value = nil
otherRow4.reload()
let otherRow5 = self?.form.rowBy(tag: "otherAlerts4") as! SegmentedRow<String>
otherRow5.value = nil
otherRow5.reload()
row.value = value
}


<<< SegmentedRow<String>("otherAlerts4"){ row in
row.title = ""
row.options = ["Rec. Bolus"]
if UserDefaultsRepository.url.value == "" {
row.hidden = true
}
}.onChange { [weak self] row in
guard let value = row.value else { return }
let otherRow = self?.form.rowBy(tag: "bgExtraAlerts") as! SegmentedRow<String>
otherRow.value = nil
otherRow.reload()
let otherRow2 = self?.form.rowBy(tag: "bgAlerts") as! SegmentedRow<String>
otherRow2.value = nil
otherRow2.reload()
let otherRow3 = self?.form.rowBy(tag: "otherAlerts") as! SegmentedRow<String>
otherRow3.value = nil
otherRow3.reload()
let otherRow4 = self?.form.rowBy(tag: "otherAlerts2") as! SegmentedRow<String>
otherRow4.value = nil
otherRow4.reload()
let otherRow5 = self?.form.rowBy(tag: "otherAlerts3") as! SegmentedRow<String>
otherRow5.value = nil
otherRow5.reload()
row.value = value
}

buildUrgentLow()
buildLow()
Expand Down Expand Up @@ -390,7 +423,8 @@ class AlarmViewController: FormViewController {
buildIOB()
buildCOB()
buildBatteryAlarm()

buildRecBolus()

buildSnoozeAll()
buildAlarmSettings()

Expand Down Expand Up @@ -3242,6 +3276,70 @@ class AlarmViewController: FormViewController {
UserDefaultsRepository.alertBatteryRepeat.value = value
}
}

func buildRecBolus(){
form
+++ Section(header: "Rec. Bolus Alert", footer: "Activates a notification alert whenever recommended bolus is above a user-defined threshold, allowing for proactive manual bolusing.") { row in
row.hidden = "$otherAlerts4 != 'Rec. Bolus'"
}
<<< SwitchRow("alertRecBolusActive"){ row in
row.title = "Active"
row.value = UserDefaultsRepository.alertRecBolusActive.value
}.onChange { [weak self] row in
guard let value = row.value else { return }
UserDefaultsRepository.alertRecBolusActive.value = value
}
<<< StepperRow("alertRecBolusAt") { row in
row.title = "Rec. Bolus threshold"
row.cell.stepper.stepValue = 0.1
row.cell.stepper.minimumValue = 0.1
row.cell.stepper.maximumValue = 50
row.value = Double(UserDefaultsRepository.alertRecBolusLevel.value)
row.displayValueFor = { value in
guard let value = value else { return nil }
return "\(Double(round(10*value)/10))"
}
}.onChange { [weak self] row in
guard let value = row.value else { return }
UserDefaultsRepository.alertRecBolusLevel.value = value
}
<<< StepperRow("alertRecBolusSnooze") { row in
row.title = "Default Snooze"
row.cell.stepper.stepValue = 5
row.cell.stepper.minimumValue = 5
row.cell.stepper.maximumValue = 60
row.value = Double(UserDefaultsRepository.alertRecBolusSnooze.value)
row.displayValueFor = { value in
guard let value = value else { return nil }
return "\(Int(value))"
}
}.onChange { [weak self] row in
guard let value = row.value else { return }
UserDefaultsRepository.alertRecBolusSnooze.value = Int(value)
}
<<< PickerInputRow<String>("alertRecBolusSound") { row in
row.title = "Sound"
row.options = soundFiles
row.value = UserDefaultsRepository.alertRecBolusSound.value
row.displayValueFor = { value in
guard let value = value else { return nil }
return "\(String(value.replacingOccurrences(of: "_", with: " ")))"
}
}.onChange { [weak self] row in
guard let value = row.value else { return }
UserDefaultsRepository.alertRecBolusSound.value = value
AlarmSound.setSoundFile(str: value)
AlarmSound.stop()
AlarmSound.playTest()
}
<<< SwitchRow("alertRecBolusRepeat"){ row in
row.title = "Repeat Sound"
row.value = UserDefaultsRepository.alertRecBolusRepeat.value
}.onChange { [weak self] row in
guard let value = row.value else { return }
UserDefaultsRepository.alertRecBolusRepeat.value = value
}
}

func buildAlarmSettings() {
form
Expand Down
Loading

0 comments on commit 27226de

Please sign in to comment.