From 6af28479d62600c93f7654b3b3146d15cffca391 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 27 Dec 2017 00:22:34 +0100 Subject: [PATCH] Disable loop if unsupported basal rate profile is selected. Fixes #31. --- README-Combo.md | 2 ++ .../plugins/PumpCombo/ComboPlugin.java | 35 +++++++++++-------- app/src/main/res/values/strings.xml | 3 +- .../java/de/jotomo/ruffy/spi/PumpState.java | 6 +++- .../jotomo/ruffyscripter/RuffyScripter.java | 6 ++-- .../commands/ReadBasalProfileCommand.java | 4 +++ 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/README-Combo.md b/README-Combo.md index 460e423e39..749083a83c 100644 --- a/README-Combo.md +++ b/README-Combo.md @@ -85,6 +85,8 @@ Usage: - The integration of the Combo with AndroidAPS is designed with the assumption that all inputs are made via AndroidAPS. Boluses entered on the pump will NOT be detected by AAPS and may therefore result in too much insulin being delivered. +- The pump's first basal rate profile is read on app start and is updated by AAPS. Manually changing + the pump's basal rate profile will lead to wrong basals being delivered and is NOT supported. - It's recommended to enable key lock on the pump to prevent bolusing from the pump, esp. when the pump was used before and quick bolusing was a habit. Also, with keylock enabled, accidentally pressing a key will NOT interrupt a running command diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java index 4dae17dba6..d43df6c4f3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java @@ -351,14 +351,22 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf // read basal profile into cache and update pump profile if needed if (!pump.initialized) { + if (stateResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) { + Notification n = new Notification(Notification.COMBO_PUMP_ALARM, + MainApp.sResources.getString(R.string.combo_force_disabled_notification), + Notification.URGENT); + n.soundId = R.raw.alarm; + MainApp.bus().post(new EventNewNotification(n)); + violationWarningRaisedForViolationAt = lowSuspendOnlyLoopEnforcedUntil; + return; + } CommandResult readBasalResult = runCommand("Reading basal profile", 2, ruffyScripter::readBasalProfile); if (!readBasalResult.success) { return; } pump.basalProfile = readBasalResult.basalProfile; - } + validBasalRateProfileSelectedOnPump = true; - if (!pump.initialized) { pump.initialized = true; MainApp.bus().post(new EventInitializationChanged()); } @@ -716,9 +724,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf if (commandResult.success) { pump.lastSuccessfulCmdTime = System.currentTimeMillis(); - } - - if (commandResult.success) { + validBasalRateProfileSelectedOnPump = commandResult.state.unsafeUsageDetected != PumpState.UNSUPPORTED_BASAL_RATE_PROFILE; updateLocalData(commandResult); } } finally { @@ -811,7 +817,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf if (commandResult == null) return; long lastViolation = 0; - if (commandResult.state.unsafeUsageDetected) { + if (commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BOLUS_TYPE) { lastViolation = System.currentTimeMillis(); } else if (commandResult.lastBolus != null && !commandResult.lastBolus.isValid) { lastViolation = commandResult.lastBolus.timestamp; @@ -823,14 +829,14 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } } if (lastViolation > 0) { - lowSuspendOnlyLoopEnforcetTill = lastViolation + 6 * 60 * 60 * 1000; - if (lowSuspendOnlyLoopEnforcetTill > System.currentTimeMillis() && violationWarningRaisedFor != lowSuspendOnlyLoopEnforcetTill) { + lowSuspendOnlyLoopEnforcedUntil = lastViolation + 6 * 60 * 60 * 1000; + if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis() && violationWarningRaisedForViolationAt != lowSuspendOnlyLoopEnforcedUntil) { Notification n = new Notification(Notification.COMBO_PUMP_ALARM, - MainApp.sResources.getString(R.string.combo_force_disabled_notification), + MainApp.sResources.getString(R.string.combo_low_suspend_forced_notification), Notification.URGENT); n.soundId = R.raw.alarm; MainApp.bus().post(new EventNewNotification(n)); - violationWarningRaisedFor = lowSuspendOnlyLoopEnforcetTill; + violationWarningRaisedForViolationAt = lowSuspendOnlyLoopEnforcedUntil; } } } @@ -1058,8 +1064,9 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } // Constraints interface - private long lowSuspendOnlyLoopEnforcetTill = 0; - private long violationWarningRaisedFor = 0; + private long lowSuspendOnlyLoopEnforcedUntil = 0; + private long violationWarningRaisedForViolationAt = 0; + private boolean validBasalRateProfileSelectedOnPump = false; @Override public boolean isLoopEnabled() { @@ -1068,7 +1075,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public boolean isClosedModeEnabled() { - return true; + return validBasalRateProfileSelectedOnPump; } @Override @@ -1103,6 +1110,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Double applyMaxIOBConstraints(Double maxIob) { - return lowSuspendOnlyLoopEnforcetTill < System.currentTimeMillis() ? maxIob : 0; + return lowSuspendOnlyLoopEnforcedUntil < System.currentTimeMillis() ? maxIob : 0; } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 406dea0cf9..957a78758d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -816,7 +816,8 @@ Use system notifications for alerts Never Requested operation not supported by pump - Unsafe usage: extended or multiwave boluses have been delivered within the last 6 hours or the selected basal rate is not 1. Loop mode has been set to low-suspend only until 6 hours after the last unsupported bolus or basal rate profile. Only normal boluses are supported in loop mode with basal rate profile 1. + Unsafe usage: extended or multiwave boluses are active. Loop mode has been set to low-suspend only 6 hours. Only normal boluses are supported in loop mode + Unsafe usage: the pump uses a different basal rate profile than the first, which is not supported. Select the first profile on the pump and refresh. A bolus with the same amount was requested within the last minute. To prevent accidental double boluses and to guard against bugs this is disallowed. Now Reading pump history diff --git a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java index 728b9f7fa0..917c563e77 100644 --- a/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java +++ b/ruffy-spi/src/main/java/de/jotomo/ruffy/spi/PumpState.java @@ -30,8 +30,12 @@ public class PumpState { public int insulinState = UNKNOWN; public int activeBasalProfileNumber; + + public static final int SAFE_USAGE = 0; + public static final int UNSUPPORTED_BOLUS_TYPE = 1; + public static final int UNSUPPORTED_BASAL_RATE_PROFILE = 2; /** True if use of an extended or multiwave bolus has been detected */ - public boolean unsafeUsageDetected; + public int unsafeUsageDetected = SAFE_USAGE; public PumpState menu(String menu) { this.menu = menu; diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 44deb879e8..3cee006ae6 100644 --- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -501,8 +501,10 @@ public class RuffyScripter implements RuffyCommands { BolusType bolusType = (BolusType) menu.getAttribute(MenuAttribute.BOLUS_TYPE); Integer activeBasalRate = (Integer) menu.getAttribute(MenuAttribute.BASAL_SELECTED); - if (bolusType != null && bolusType != BolusType.NORMAL || !activeBasalRate.equals(1)) { - state.unsafeUsageDetected = true; + if (!activeBasalRate.equals(1)) { + state.unsafeUsageDetected = PumpState.UNSUPPORTED_BASAL_RATE_PROFILE; + } else if (bolusType != null && bolusType != BolusType.NORMAL) { + state.unsafeUsageDetected = PumpState.UNSUPPORTED_BOLUS_TYPE; } else if (tbrPercentage != null && tbrPercentage != 100) { state.tbrActive = true; Double displayedTbr = (Double) menu.getAttribute(MenuAttribute.TBR); diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadBasalProfileCommand.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadBasalProfileCommand.java index d778d08c13..1cd3f1df32 100644 --- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadBasalProfileCommand.java +++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/ReadBasalProfileCommand.java @@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory; import java.util.Arrays; import de.jotomo.ruffy.spi.BasalProfile; +import de.jotomo.ruffy.spi.PumpState; public class ReadBasalProfileCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(ReadBasalProfileCommand.class); @@ -17,6 +18,9 @@ public class ReadBasalProfileCommand extends BaseCommand { @Override public void execute() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + if (scripter.readPumpStateInternal().unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) { + throw new CommandException("Active basal rate profile != 1"); + } scripter.navigateToMenu(MenuType.BASAL_1_MENU); scripter.verifyMenuIsDisplayed(MenuType.BASAL_1_MENU); scripter.pressCheckKey();