Disable closed loop under unsafe conditions.

This commit is contained in:
Johannes Mockenhaupt 2017-11-01 01:44:31 +01:00
parent 8d3947dc7f
commit 4da160a951
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
6 changed files with 102 additions and 17 deletions

View file

@ -32,10 +32,13 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI;
import info.nightscout.utils.DateUtil;
@ -46,7 +49,7 @@ import static de.jotomo.ruffy.spi.BolusProgressReporter.State.FINISHED;
/**
* Created by mike on 05.08.2016.
*/
public class ComboPlugin implements PluginBase, PumpInterface {
public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterface {
private static Logger log = LoggerFactory.getLogger(ComboPlugin.class);
private boolean fragmentEnabled = false;
@ -148,7 +151,9 @@ public class ComboPlugin implements PluginBase, PumpInterface {
@Override
public boolean isEnabled(int type) {
return type == PUMP && fragmentEnabled;
if (type == PluginBase.PUMP) return fragmentEnabled;
else if (type == PluginBase.CONSTRAINTS) return fragmentEnabled;
return false;
}
@Override
@ -249,10 +254,14 @@ public class ComboPlugin implements PluginBase, PumpInterface {
}
private void updateLocalData(CommandResult result) {
if (result.reservoirLevel != PumpState.UNKNOWN)
if (result.reservoirLevel != PumpState.UNKNOWN) {
pump.reservoirLevel = result.reservoirLevel;
if (result.lastBolus != null)
}
if (result.lastBolus != null) {
pump.lastBolus = result.lastBolus;
} else if (result.history != null && !result.history.bolusHistory.isEmpty()) {
pump.lastBolus = result.history.bolusHistory.get(0);
}
pump.state = result.state;
MainApp.bus().post(new EventComboPumpUpdateGUI());
}
@ -610,11 +619,13 @@ public class ComboPlugin implements PluginBase, PumpInterface {
if (!commandResult.success && retries > 0) {
for (int retryAttempts = 1; !commandResult.success && retryAttempts <= retries; retryAttempts++) {
log.debug("Command was not successful, retries request, doing retry #" + retryAttempts);
log.debug("Command was not successful, retries requested, doing retry #" + retryAttempts);
commandResult = commandExecution.execute();
}
}
checkForUnsupportedBoluses(commandResult);
pump.lastCmdResult = commandResult;
pump.lastConnectionAttempt = System.currentTimeMillis();
if (commandResult.success) {
@ -629,6 +640,31 @@ public class ComboPlugin implements PluginBase, PumpInterface {
return commandResult;
}
private void checkForUnsupportedBoluses(CommandResult commandResult) {
long lastViolation = 0;
if (commandResult.lastBolus != null && !commandResult.lastBolus.isValid) {
lastViolation = commandResult.lastBolus.timestamp;
} else if (commandResult.history != null) {
for (Bolus bolus : commandResult.history.bolusHistory) {
if (!bolus.isValid && bolus.timestamp > lastViolation) {
lastViolation = bolus.timestamp;
}
}
}
if (lastViolation > 0) {
closedLoopDisabledUntil = lastViolation + 6 * 60 * 60 * 1000;
if (closedLoopDisabledUntil > System.currentTimeMillis()) {
// TODO add message to either Combo tab or its errors popup
Notification n = new Notification(Notification.COMBO_PUMP_ALARM,
MainApp.sResources.getString(R.string.combo_force_disabled),
Notification.URGENT);
n.soundId = R.raw.alarm;
MainApp.bus().post(new EventNewNotification(n));
}
}
}
// TODO rename to checkState or so and also check time (& date) of pump
private void checkForTbrMismatch() {
// detectTbrMismatch(): 'quick' check with no overhead on the pump side
@ -869,4 +905,52 @@ public class ComboPlugin implements PluginBase, PumpInterface {
public boolean isFakingTempsByExtendedBoluses() {
return false;
}
// Constraints interface
private long closedLoopDisabledUntil = 0;
@Override
public boolean isLoopEnabled() {
return true;
}
@Override
public boolean isClosedModeEnabled() {
return closedLoopDisabledUntil < System.currentTimeMillis();
}
@Override
public boolean isAutosensModeEnabled() {
return true;
}
@Override
public boolean isAMAModeEnabled() {
return true;
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
return percentRate;
}
@Override
public Double applyBolusConstraints(Double insulin) {
return insulin;
}
@Override
public Integer applyCarbsConstraints(Integer carbs) {
return carbs;
}
@Override
public Double applyMaxIOBConstraints(Double maxIob) {
return maxIob;
}
}

View file

@ -791,5 +791,6 @@
<string name="combo_pump_bolus_verification_failed">Bolus delivery verification failed. The pump history will be read again on the next loop run or when refreshing from the Combo page. Please check and bolus again if needed.</string>
<string name="combo_pump_unsupported_operation">Requested operation not supported by pump</string>
<string name="combo_bolus_bolus_delivery_failed">Bolus delivery failed. A (partial) bolus might have been delivered. Attempting to update history from pump. Please check the Combo page and bolus again as needed.</string>
<string name="combo_force_disabled">Unsafe usage: extended or multiwave boluses have been delivered within the last 6h. Closed loop mode forcefully disabled. Only normal boluses are supported when running in closed loop mode.</string>
</resources>

View file

@ -2,12 +2,15 @@ package de.jotomo.ruffy.spi.history;
public class Bolus extends HistoryRecord {
public final double amount;
public final boolean isValid;
public Bolus(long timestamp, double amount) {
public Bolus(long timestamp, double amount, boolean isValid) {
super(timestamp);
this.amount = amount;
this.isValid = isValid;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -16,6 +19,7 @@ public class Bolus extends HistoryRecord {
Bolus bolus = (Bolus) o;
if (timestamp != bolus.timestamp) return false;
if (isValid != bolus.isValid) return false;
return Double.compare(bolus.amount, amount) == 0;
}
@ -25,6 +29,7 @@ public class Bolus extends HistoryRecord {
long temp;
result = (int) (timestamp ^ (timestamp >>> 32));
temp = Double.doubleToLongBits(amount);
result = result + (isValid ? 1 : 0);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}

View file

@ -3,9 +3,10 @@ package de.jotomo.ruffy.spi.history;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/** History data as read from the pump's My Data menu.
* Records are ordered from newest to oldest, so the first record is always the newest. */
public class PumpHistory {
@NonNull
public List<Bolus> bolusHistory = new ArrayList<>();

View file

@ -127,14 +127,11 @@ public class ReadHistoryCommand extends BaseCommand {
@NonNull
private Bolus readBolusRecord() {
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
// Could also be extended, multiwave
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
if (!bolusType.equals(BolusType.NORMAL)) {
throw new CommandException("Unsupported bolus type encountered: " + bolusType);
}
boolean isValid = bolusType == BolusType.NORMAL;
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
long recordDate = readRecordDate();
return new Bolus(recordDate, bolus);
return new Bolus(recordDate, bolus, isValid);
}
private void readErrorRecords(long requestedTime) {

View file

@ -31,14 +31,11 @@ public class ReadReservoirLevelAndLastBolus extends BaseCommand {
@NonNull
private Bolus readBolusRecord() {
scripter.verifyMenuIsDisplayed(MenuType.BOLUS_DATA);
// Could also be extended, multiwave
BolusType bolusType = (BolusType) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_TYPE);
if (!bolusType.equals(BolusType.NORMAL)) {
throw new CommandException("Unsupported bolus type encountered: " + bolusType);
}
boolean isValid = bolusType == BolusType.NORMAL;
Double bolus = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS);
long recordDate = readRecordDate();
return new Bolus(recordDate, bolus);
return new Bolus(recordDate, bolus, isValid);
}
private long readRecordDate() {