From 3a8cc128536fa6233f1f1f7b8ed3022e94afedc6 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Tue, 7 Jan 2020 19:26:01 +0100 Subject: [PATCH] Add fixed 'pump unreachable' alerts for Omnipod --- .../interfaces/PumpDescription.java | 5 +++ .../androidaps/interfaces/PumpInterface.java | 5 +++ .../plugins/pump/common/defs/PumpType.java | 45 ++++++++++--------- .../pump/omnipod/OmnipodPumpPlugin.java | 25 +++++++++++ .../androidaps/utils/LocalAlertUtils.java | 44 ++++++++++++++---- 5 files changed, 96 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java index e4a02883e8..1027792cc3 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java @@ -55,6 +55,7 @@ public class PumpDescription { public boolean supportsTDDs; public boolean needsManualTDDLoad; + public boolean hasFixedUnreachableAlert; public void resetSettings() { isBolusCapable = true; @@ -87,6 +88,8 @@ public class PumpDescription { supportsTDDs = false; needsManualTDDLoad = true; + + hasFixedUnreachableAlert = false; } public void setPumpDescription(PumpType pumpType) { @@ -134,6 +137,8 @@ public class PumpDescription { needsManualTDDLoad = pumpCapability.hasCapability(PumpCapability.ManualTDDLoad); is30minBasalRatesCapable = pumpCapability.hasCapability(PumpCapability.BasalRate30min); + + hasFixedUnreachableAlert = pumpType.getHasFixedUnreachableAlert(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index 025f10076d..0a0bc2da13 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -99,4 +99,9 @@ public interface PumpInterface { */ void timeDateOrTimeZoneChanged(); + /* Only used for pump types where hasFixedUnreachableAlert=true */ + default boolean isFixedUnreachableAlertTimeoutExceeded() { + return false; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java index 81ae5556d3..d34109bed5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java @@ -23,7 +23,7 @@ public enum PumpType { new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // new DoseSettings(10, 30, 24 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities), // + 0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities, false), // // Cellnovo @@ -31,7 +31,7 @@ public enum PumpType { new DoseSettings(0.05d, 30, 24 * 60, 1d, null), PumpTempBasalType.Percent, new DoseSettings(5, 30, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // + 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities, false), // // Accu-Chek @@ -39,32 +39,32 @@ public enum PumpType { new DoseSettings(0.1d, 15, 12 * 60, 0.1d), // PumpTempBasalType.Percent, new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities), // + 0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities, false), // AccuChekSpirit("Accu-Chek Spirit", ManufacturerType.Roche, "Spirit", 0.1d, null, // new DoseSettings(0.1d, 15, 12 * 60, 0.1d), // PumpTempBasalType.Percent, new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities), // + 0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities, false), // AccuChekInsight("Accu-Chek Insight", ManufacturerType.Roche, "Insight", 0.05d, DoseStepSize.InsightBolus, // new DoseSettings(0.05d, 15, 24 * 60, 0.05d), // PumpTempBasalType.Percent, new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.02d, 0.01d, null, PumpCapability.InsightCapabilities), // + 0.02d, 0.01d, null, PumpCapability.InsightCapabilities, false), // AccuChekInsightBluetooth("Accu-Chek Insight", ManufacturerType.Roche, "Insight", 0.01d, null, // new DoseSettings(0.01d, 15, 24 * 60, 0.05d), // PumpTempBasalType.Percent, new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.02d, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), // + 0.02d, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities, false), // // Animas AnimasVibe("Animas Vibe", ManufacturerType.Animas, "Vibe", 0.05d, null, // AnimasBolus? new DoseSettings(0.05d, 30, 12 * 60, 0.05d), // PumpTempBasalType.Percent, // new DoseSettings(10, 30, 24 * 60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), // + 0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities, false), // AnimasPing("Animas Ping", "Ping", AnimasVibe), @@ -73,19 +73,19 @@ public enum PumpType { new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // - 0.04d, 0.01d, null, PumpCapability.DanaCapabilities), + 0.04d, 0.01d, null, PumpCapability.DanaCapabilities, false), DanaRKorean("DanaR Korean", ManufacturerType.Sooil, "DanaRKorean", 0.05d, null, // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // - 0.1d, 0.01d, null, PumpCapability.DanaCapabilities), + 0.1d, 0.01d, null, PumpCapability.DanaCapabilities, false), DanaRS("DanaRS", ManufacturerType.Sooil, "DanaRS", 0.05d, null, // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities), + 0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities, false), DanaRv2("DanaRv2", "DanaRv2", DanaRS), @@ -95,20 +95,20 @@ public enum PumpType { new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), + 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities, true), Insulet_Omnipod_Dash("Insulet Omnipod Dash", ManufacturerType.Insulet, "Omnipod Dash", 0.05d, null, // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // TODO just copied OmniPod for now + 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities, true), // TODO just copied OmniPod for now // Medtronic Medtronic_512_712("Medtronic 512/712", ManufacturerType.Medtronic, "512/712", 0.1d, null, // new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.05d, 0.05d, null, PumpCapability.MedtronicCapabilities), // + 0.05d, 0.05d, null, PumpCapability.MedtronicCapabilities, false), // Medtronic_515_715("Medtronic 515/715", "515/715", Medtronic_512_712), Medtronic_522_722("Medtronic 522/722", "522/722", Medtronic_512_712), @@ -117,7 +117,7 @@ public enum PumpType { new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.MedtronicCapabilities), // + 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.MedtronicCapabilities, false), // Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", "554/754 (Veo)", Medtronic_523_723_Revel), // TODO @@ -125,14 +125,14 @@ public enum PumpType { new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // + 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities, false), // // Tandem TandemTSlim("Tandem t:slim", ManufacturerType.Tandem, "t:slim", 0.01d, null, // new DoseSettings(0.01d, 15, 8 * 60, 0.4d), PumpTempBasalType.Percent, new DoseSettings(1, 15, 8 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // - 0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities), + 0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities, false), TandemTFlex("Tandem t:flex", "t:flex", TandemTSlim), // TandemTSlimG4("Tandem t:slim G4", "t:slim G4", TandemTSlim), // @@ -156,6 +156,7 @@ public enum PumpType { private double baseBasalStep; // private DoseStepSize baseBasalSpecialSteps; // private PumpCapability pumpCapability; + private boolean hasFixedUnreachableAlert; private PumpType parent; private static Map mapByDescription; @@ -193,14 +194,15 @@ public enum PumpType { PumpType(String description, ManufacturerType manufacturer, String model, double bolusSize, DoseStepSize specialBolusSize, // DoseSettings extendedBolusSettings, // PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // - double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { - this(description, manufacturer, model, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability); + double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability, boolean hasFixedUnreachableAlert) { + this(description, manufacturer, model, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability, hasFixedUnreachableAlert); } PumpType(String description, ManufacturerType manufacturer, String model, double bolusSize, DoseStepSize specialBolusSize, // DoseSettings extendedBolusSettings, // PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // - double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { + double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, // + PumpCapability pumpCapability, boolean hasFixedUnreachableAlert) { this.description = description; this.manufacturer = manufacturer; this.model = model; @@ -215,9 +217,12 @@ public enum PumpType { this.baseBasalStep = baseBasalStep; this.baseBasalSpecialSteps = baseBasalSpecialSteps; this.pumpCapability = pumpCapability; + this.hasFixedUnreachableAlert = hasFixedUnreachableAlert; } - + public boolean getHasFixedUnreachableAlert() { + return hasFixedUnreachableAlert; + } public String getDescription() { return description; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index d0d10ff733..016fc3380e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -69,6 +69,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; @@ -103,6 +104,7 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump private Profile currentProfile; + private static long UNREACHABLE_ALERT_THRESHOLD_MILLIS = T.mins(30).msecs(); private OmnipodPumpPlugin() { @@ -918,4 +920,27 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump } + @Override + public boolean isFixedUnreachableAlertTimeoutExceeded() { + getPodPumpStatusObject(); + + if (pumpStatusLocal.lastConnection != 0 || pumpStatusLocal.lastErrorConnection != 0) { + if (pumpStatusLocal.lastConnection + UNREACHABLE_ALERT_THRESHOLD_MILLIS < System.currentTimeMillis()) { + if (pumpStatusLocal.lastErrorConnection > pumpStatusLocal.lastConnection) { + // We exceeded the alert threshold, and our last connection failed + // We should show an alert + return true; + } + + // Don't trigger an alert when we exceeded the thresholds, but the last communication was successful + // This happens when we simply didn't need to send any commands to the pump + return false; + } + + } + + // If we have no last connection and error data, don't show any alert + // FIXME is this appropriate? + return false; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java b/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java index 282ad1aa55..0cb3f386fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java @@ -35,24 +35,52 @@ public class LocalAlertUtils { } public static void checkPumpUnreachableAlarm(long lastConnection, boolean isStatusOutdated) { + PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump(); + if(activePump != null && activePump.getPumpDescription().hasFixedUnreachableAlert) { + checkPumpUnreachableAlarmStatic(activePump); + } else { + checkPumpUnreachableAlarmConfigured(lastConnection, isStatusOutdated); + } + } + + private static void checkPumpUnreachableAlarmStatic(PumpInterface pump) { + if(pump == null) { + return; + } + + if(pump.isFixedUnreachableAlertTimeoutExceeded()) { + log.debug("Generating static pump unreachable alarm."); + + showUnreachableNotification(T.mins(30).msecs()); + } else { + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PUMP_UNREACHABLE)); + } + } + + private static void checkPumpUnreachableAlarmConfigured(long lastConnection, boolean isStatusOutdated) { boolean alarmTimeoutExpired = lastConnection + pumpUnreachableThreshold() < System.currentTimeMillis(); boolean nextAlarmOccurrenceReached = SP.getLong("nextPumpDisconnectedAlarm", 0L) < System.currentTimeMillis(); if (Config.APS && SP.getBoolean(MainApp.gs(R.string.key_enable_pump_unreachable_alert), true) && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !LoopPlugin.getPlugin().isDisconnected()) { - log.debug("Generating pump unreachable alarm. lastConnection: " + DateUtil.dateAndTimeString(lastConnection) + " isStatusOutdated: " + isStatusOutdated); - Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.gs(R.string.pump_unreachable), Notification.URGENT); - n.soundId = R.raw.alarm; - SP.putLong("nextPumpDisconnectedAlarm", System.currentTimeMillis() + pumpUnreachableThreshold()); - RxBus.INSTANCE.send(new EventNewNotification(n)); - if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) { - NSUpload.uploadError(n.text); - } + log.debug("Generating configured pump unreachable alarm. lastConnection: " + DateUtil.dateAndTimeString(lastConnection) + " isStatusOutdated: " + isStatusOutdated); + + showUnreachableNotification(pumpUnreachableThreshold()); } if (!isStatusOutdated && !alarmTimeoutExpired) RxBus.INSTANCE.send(new EventDismissNotification(Notification.PUMP_UNREACHABLE)); } + private static void showUnreachableNotification(long nextAlarmTimeoutMillis) { + Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.gs(R.string.pump_unreachable), Notification.URGENT); + n.soundId = R.raw.alarm; + SP.putLong("nextPumpDisconnectedAlarm", System.currentTimeMillis() + nextAlarmTimeoutMillis); + RxBus.INSTANCE.send(new EventNewNotification(n)); + if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) { + NSUpload.uploadError(n.text); + } + } + /*Presnoozes the alarms with 5 minutes if no snooze exists. * Call only at startup! */