Add fast drop and fast rise alerts
This commit is contained in:
parent
afb0a6efba
commit
9363fb4a81
|
@ -17,6 +17,12 @@ enum ConstantsDefaultAlertLevels {
|
|||
static let high = 170
|
||||
static let low = 70
|
||||
|
||||
// blood glucose fast drop delta alert in mgdl
|
||||
static let fastdrop = 10
|
||||
|
||||
// blood glucose fast rise delta alert in mgdl
|
||||
static let fastrise = 10
|
||||
|
||||
// in minutes, after how many minutes of now reading should alert be raised
|
||||
static let missedReading = 30
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ enum ConstantsNotifications {
|
|||
static let missedReadingAlert = "missedReadingAlert"
|
||||
/// battery low
|
||||
static let batteryLow = "batteryLow"
|
||||
/// fast drop
|
||||
static let fastdrop = "fastDrop"
|
||||
}
|
||||
|
||||
/// identifiers for alert notifications
|
||||
|
@ -34,6 +36,10 @@ enum ConstantsNotifications {
|
|||
static let missedReadingAlert = "missedReadingAlert"
|
||||
/// battery low
|
||||
static let batteryLow = "batteryLow"
|
||||
/// fast drop
|
||||
static let fastDropAlert = "fastDropAlert"
|
||||
/// fast rise
|
||||
static let fastRiseAlert = "fastRiseAlert"
|
||||
}
|
||||
|
||||
/// identifiers for calibration requests
|
||||
|
|
|
@ -5,7 +5,7 @@ public enum AlertKind:Int, CaseIterable {
|
|||
// when adding alertkinds, try to add new cases at the end (ie 7, ...)
|
||||
// if this is done in the middle ((eg rapid rise alert might seem better positioned after veryhigh), then a database migration would be required, because the rawvalue is stored as Int16 in the coredata, namely the alertkind
|
||||
// the order of the alerts will also be the order in the settings
|
||||
|
||||
|
||||
case verylow = 0
|
||||
case low = 1
|
||||
case high = 2
|
||||
|
@ -13,13 +13,15 @@ public enum AlertKind:Int, CaseIterable {
|
|||
case missedreading = 4
|
||||
case calibration = 5
|
||||
case batterylow = 6
|
||||
|
||||
case fastdrop = 7
|
||||
case fastrise = 8
|
||||
|
||||
/// example, low alert needs a value = value below which alert needs to fire - there's actually no alert right now that doesn't need a value, in iosxdrip there was the iphonemuted alert, but I removed this here. Function remains, never now it might come back
|
||||
///
|
||||
/// probably only useful in UI - named AlertKind and not AlertType because there's already an AlertType which has a different goal
|
||||
func needsAlertValue() -> Bool {
|
||||
switch self {
|
||||
case .low, .high, .verylow,.veryhigh,.missedreading,.calibration,.batterylow:
|
||||
case .low, .high, .verylow,.veryhigh,.missedreading,.calibration,.batterylow,.fastdrop,.fastrise:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +31,8 @@ public enum AlertKind:Int, CaseIterable {
|
|||
/// will only be useful in UI
|
||||
func valueNeedsConversionToMmol() -> Bool {
|
||||
switch self {
|
||||
|
||||
case .low, .high, .verylow, .veryhigh:
|
||||
|
||||
case .low, .high, .verylow, .veryhigh, .fastdrop, .fastrise:
|
||||
return true
|
||||
case .missedreading, .calibration, .batterylow:
|
||||
return false
|
||||
|
@ -59,6 +61,10 @@ public enum AlertKind:Int, CaseIterable {
|
|||
} else {
|
||||
return ConstantsDefaultAlertLevels.defaultBatteryAlertLevelMiaoMiao
|
||||
}
|
||||
case .fastdrop:
|
||||
return ConstantsDefaultAlertLevels.fastdrop;
|
||||
case .fastrise:
|
||||
return ConstantsDefaultAlertLevels.fastrise;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +86,10 @@ public enum AlertKind:Int, CaseIterable {
|
|||
return "calibration"
|
||||
case .batterylow:
|
||||
return "batterylow"
|
||||
case .fastdrop:
|
||||
return "fastdrop"
|
||||
case .fastrise:
|
||||
return "fastrise"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +141,32 @@ public enum AlertKind:Int, CaseIterable {
|
|||
} else {return (false, nil, nil, nil)}
|
||||
} else {return (false, nil, nil, nil)}
|
||||
|
||||
case .fastdrop:
|
||||
// if alertEntry not enabled, return false
|
||||
if !currentAlertEntry.alertType.enabled {return (false, nil, nil, nil)}
|
||||
|
||||
if let lastBgReading = lastBgReading, let lastButOneBgReading = lastButOneBgReading {
|
||||
// first check if calculatedValue > 0.0, never know that it's not been checked by caller
|
||||
if lastBgReading.calculatedValue == 0.0 {return (false, nil, nil, nil)}
|
||||
// now do the actual check if alert is applicable or not
|
||||
if lastButOneBgReading.calculatedValue - lastBgReading.calculatedValue > Double(currentAlertEntry.value) {
|
||||
return (true, lastBgReading.unitizedDeltaString(previousBgReading: lastButOneBgReading, showUnit: true, highGranularity: true, mgdl: UserDefaults.standard.bloodGlucoseUnitIsMgDl), createAlertTitleForBgReadingAlerts(bgReading: lastBgReading, alertKind: self), nil)
|
||||
} else {return (false, nil, nil, nil)}
|
||||
} else {return (false, nil, nil, nil)}
|
||||
|
||||
case .fastrise:
|
||||
// if alertEntry not enabled, return false
|
||||
if !currentAlertEntry.alertType.enabled {return (false, nil, nil, nil)}
|
||||
|
||||
if let lastBgReading = lastBgReading, let lastButOneBgReading = lastButOneBgReading {
|
||||
// first check if calculatedValue > 0.0, never know that it's not been checked by caller
|
||||
if lastBgReading.calculatedValue == 0.0 {return (false, nil, nil, nil)}
|
||||
// now do the actual check if alert is applicable or not
|
||||
if lastBgReading.calculatedValue - lastButOneBgReading.calculatedValue > Double(currentAlertEntry.value) {
|
||||
return (true, lastBgReading.unitizedDeltaString(previousBgReading: lastButOneBgReading, showUnit: true, highGranularity: true, mgdl: UserDefaults.standard.bloodGlucoseUnitIsMgDl), createAlertTitleForBgReadingAlerts(bgReading: lastBgReading, alertKind: self), nil)
|
||||
} else {return (false, nil, nil, nil)}
|
||||
} else {return (false, nil, nil, nil)}
|
||||
|
||||
case .missedreading:
|
||||
// if no valid lastbgreading then there's definitely no need to plan an alert
|
||||
guard let lastBgReading = lastBgReading else {return (false, nil, nil, nil)}
|
||||
|
@ -267,6 +303,10 @@ public enum AlertKind:Int, CaseIterable {
|
|||
return ConstantsNotifications.NotificationIdentifiersForCalibration.subsequentCalibrationRequest
|
||||
case .batterylow:
|
||||
return ConstantsNotifications.NotificationIdentifiersForAlerts.batteryLow
|
||||
case .fastdrop:
|
||||
return ConstantsNotifications.NotificationIdentifiersForAlerts.fastDropAlert
|
||||
case .fastrise:
|
||||
return ConstantsNotifications.NotificationIdentifiersForAlerts.fastRiseAlert
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,6 +328,10 @@ public enum AlertKind:Int, CaseIterable {
|
|||
return Texts_Alerts.calibrationNeededAlertTitle
|
||||
case .batterylow:
|
||||
return Texts_Alerts.batteryLowAlertTitle
|
||||
case .fastdrop:
|
||||
return Texts_Alerts.fastDropTitle
|
||||
case .fastrise:
|
||||
return Texts_Alerts.fastRiseTitle
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,8 +339,8 @@ public enum AlertKind:Int, CaseIterable {
|
|||
/// What is this text ?
|
||||
func valueUnitText(transmitterType:CGMTransmitterType?) -> String {
|
||||
switch self {
|
||||
|
||||
case .verylow, .low, .high, .veryhigh:
|
||||
|
||||
case .verylow, .low, .high, .veryhigh, .fastdrop, .fastrise:
|
||||
return UserDefaults.standard.bloodGlucoseUnitIsMgDl ? Texts_Common.mgdl:Texts_Common.mmol
|
||||
case .missedreading:
|
||||
return Texts_Common.minutes
|
||||
|
|
|
@ -137,27 +137,16 @@ public class AlertManager:NSObject {
|
|||
if latestBgReadings.count > 1 {
|
||||
lastButOneBgREading = latestBgReadings[1]
|
||||
}
|
||||
|
||||
|
||||
// alerts are checked in order of importance - there should be only one alert raised, except missed reading alert which will always be checked.
|
||||
// first check very low alert
|
||||
if (!checkAlertAndFire(alertKind: .verylow, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)) {
|
||||
// very low not fired, check low alert - if very low alert snoozed, skip the check for low alert and continue to next step
|
||||
if getSnoozeParameters(alertKind: AlertKind.verylow).getSnoozeValue().isSnoozed || (!checkAlertAndFire(alertKind: .low, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)) {
|
||||
// low not fired, check very high alert
|
||||
if (!checkAlertAndFire(alertKind: .veryhigh, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)) {
|
||||
// very high not fired, check high alert - if very high alert snoozed, skip the check for high alert and continue to next step
|
||||
if getSnoozeParameters(alertKind: AlertKind.veryhigh).getSnoozeValue().isSnoozed || (!checkAlertAndFire(alertKind: .high, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)) {
|
||||
// very high not fired check calibration alert
|
||||
if (!checkAlertAndFire(alertKind: .calibration, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)) {
|
||||
// finally let's check the battery level alert
|
||||
_ = checkAlertAndFire(alertKind: .batterylow, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// set missed reading alert, this will be a future planned alert
|
||||
|
||||
// TODO original implementation ignores isSnoozed for .calibration and .batterylow
|
||||
// only raise first alert that's been tripped
|
||||
let alertsByPreference : [AlertKind] = [.fastdrop, .verylow, .low, .fastrise, .veryhigh, .high, .calibration, .batterylow]
|
||||
_ = alertsByPreference.first(where: { (alertKind:AlertKind) -> Bool in
|
||||
let isSnoozed = getSnoozeParameters(alertKind: alertKind).getSnoozeValue().isSnoozed
|
||||
return !isSnoozed && checkAlertAndFire(alertKind: alertKind, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)
|
||||
})
|
||||
|
||||
// the missed reading alert will be a future planned alert
|
||||
_ = checkAlertAndFire(alertKind: .missedreading, lastBgReading: lastBgReading, lastButOneBgREading: lastButOneBgREading, lastCalibration: lastCalibration, transmitterBatteryInfo: transmitterBatteryInfo)
|
||||
} else {
|
||||
trace("in checkAlerts, latestBgReadings is older than %{public}@ minutes", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, maxAgeOfLastBgReadingInSeconds.description)
|
||||
|
@ -349,7 +338,7 @@ public class AlertManager:NSObject {
|
|||
|
||||
} // if snoozePeriodInMinutes or snoozeTimeStamp is nil (which shouldn't be the case) continue without taking into account the snooze status
|
||||
|
||||
case .calibration, .batterylow, .low, .high, .verylow, .veryhigh:
|
||||
case .calibration, .batterylow, .low, .high, .verylow, .veryhigh, .fastdrop, .fastrise:
|
||||
trace("in checkAlertAndFire, alert %{public}@ is currently snoozed", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging())
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -33,6 +33,14 @@ class Texts_Alerts {
|
|||
return NSLocalizedString("alerts_batterylow", tableName: filename, bundle: Bundle.main, value: "Battery Low Alert", comment: "transmitter battery low, this is the title of the alert notification, also in alert settings list, for the name of the alert")
|
||||
}()
|
||||
|
||||
static let fastDropTitle: String = {
|
||||
return NSLocalizedString("alerts_fastdrop", tableName: filename, bundle: Bundle.main, value: "Fast Drop Alert", comment: "When fast drop alert rises, this is the start of the text shown in the title of the alert notification, also in alert settings list, for the name of the alert")
|
||||
}()
|
||||
|
||||
static let fastRiseTitle: String = {
|
||||
return NSLocalizedString("alerts_fastrise", tableName: filename, bundle: Bundle.main, value: "Fast Rise Alert", comment: "When fast drop alert rises, this is the start of the text shown in the title of the alert notification, also in alert settings list, for the name of the alert")
|
||||
}()
|
||||
|
||||
static let snooze: String = {
|
||||
return NSLocalizedString("alerts_snooze", tableName: filename, bundle: Bundle.main, value: "Snooze", comment: "Action text for alerts. This is the button that allows to snooze the alert")
|
||||
}()
|
||||
|
|
Loading…
Reference in New Issue