Disable loop if unsupported basal rate profile is selected. Fixes #31.

This commit is contained in:
Johannes Mockenhaupt 2017-12-27 00:22:34 +01:00
parent c84ba24c77
commit 6af28479d6
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
6 changed files with 38 additions and 18 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -816,7 +816,8 @@
<string name="raise_urgent_alarms_as_android_notification">Use system notifications for alerts</string>
<string name="combo_pump_never_connected">Never</string>
<string name="combo_pump_unsupported_operation">Requested operation not supported by pump</string>
<string name="combo_force_disabled_notification">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.</string>
<string name="combo_low_suspend_forced_notification">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</string>
<string name="combo_force_disabled_notification">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.</string>
<string name="bolus_frequency_exceeded">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.</string>
<string name="combo_pump_connected_now">Now</string>
<string name="combo_activity_reading_pump_history">Reading pump history</string>

View file

@ -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;

View file

@ -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);

View file

@ -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();