Merge pull request #4 from jotomo/verify-record-date-after-bolus-cancel

Verify and return delivered bolus amount in BolusCommand
This commit is contained in:
Johannes Mockenhaupt 2017-12-09 19:41:16 +01:00 committed by GitHub
commit cf142a4538
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 46 deletions

View file

@ -14,7 +14,9 @@
- [ ] notification must also appear on smartwatch
- [ ] An error during bolus must yield an error in AAPS
- [ ] An error during bolus must yield a notification on a smartwatch
- [ ] Bolusing e.g. 4 U if reservoir has only 2 U must yield a usable error
- [ ] Test bolusing a bolus bigger than what's left in the reservoir. A message to check what
was actually delivered must appear (this is a corner-case where when practically can't
check what was actually delivered).
- [ ] Pressing a button on the pump before bolus delivery started must be handled gracefully
- [ ] Same as above, but moving pump out of range
- [ ] Pressing a button on the pump after bolus delivery has started must be handled

View file

@ -471,46 +471,21 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
detailedBolusInfo.isSMB ? nullBolusProgressReporter : bolusProgressReporter));
bolusInProgress = false;
if (!cancelBolus && bolusCmdResult.success) {
detailedBolusInfo.date = bolusCmdResult.state.timestamp;
if (bolusCmdResult.delivered > 0) {
detailedBolusInfo.insulin = bolusCmdResult.delivered;
detailedBolusInfo.source = Source.USER;
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
return new PumpEnactResult().success(true).enacted(true)
.bolusDelivered(detailedBolusInfo.insulin)
}
return new PumpEnactResult()
.success(bolusCmdResult.success)
.enacted(bolusCmdResult.delivered > 0)
.bolusDelivered(bolusCmdResult.delivered)
.carbsDelivered(detailedBolusInfo.carbs);
}
// the remainder of this method checks what was actually delivered based on pump history
// in case of error or cancellation
CommandResult historyResult = runCommand(null, 1,
() -> ruffyScripter.readHistory(new PumpHistoryRequest().bolusHistory(PumpHistoryRequest.LAST)));
if (!historyResult.success || historyResult.history == null || historyResult.history.bolusHistory.isEmpty()) {
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.sResources.getString(R.string.combo_bolus_bolus_delivery_failed));
}
Bolus lastPumpBolus = historyResult.history.bolusHistory.get(0);
if (cancelBolus) {
// if cancellation was requested, the delivered bolus is allowed to differ from requested
} else if (lastPumpBolus == null || Math.abs(lastPumpBolus.amount - detailedBolusInfo.insulin) > 0.01
|| System.currentTimeMillis() - lastPumpBolus.timestamp > 5 * 60 * 1000) {
return new PumpEnactResult().success(false).enacted(false).
comment(MainApp.sResources.getString(R.string.combo_bolus_bolus_delivery_failed));
}
if (lastPumpBolus != null && (lastPumpBolus.amount > 0)) {
detailedBolusInfo.insulin = lastPumpBolus.amount;
detailedBolusInfo.source = Source.USER;
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
return new PumpEnactResult().success(true).enacted(true)
.bolusDelivered(lastPumpBolus.amount).carbsDelivered(detailedBolusInfo.carbs);
} else {
return new PumpEnactResult().success(true).enacted(false);
}
} finally {
// BolusCommand.execute() intentionally doesn't close the progress dialog if an error
// occurred so it stays open while the connection was re-established if needed and/or
// this method did recovery
// BolusCommand.execute() intentionally doesn't close the progress dialog (indirectly
// by reporting 100% progress) if an error occurred so it stays open while the connection
// was re-established if needed and/or this method did recovery
bolusProgressReporter.report(FINISHED, 100, 0);
pump.activity = null;
MainApp.bus().post(new EventComboPumpUpdateGUI());

View file

@ -811,7 +811,7 @@
<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_bolus_bolus_delivery_failed">Bolus delivery failed. A (partial) bolus might have been delivered. Attempting to update history from pump. Please the pump and treatments tabs and bolus again as needed.</string>
<string name="combo_bolus_bolus_delivery_failed">Bolus delivery failed. A (partial) bolus might have been delivered. Please check the pump and the treatments tabs and bolus again as needed.</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="bolus_frequency_exceeded">A bolus with the same amount was requested within the last minute. For safety reasons this is disallowed.</string>
<string name="combo_pump_connected_now">Now</string>

View file

@ -13,13 +13,13 @@ public class CommandResult {
public boolean success;
/** State of the pump *after* command execution. */
public PumpState state;
/** Bolus actually delivered if request was a bolus command. */
public double delivered;
/** History if requested by the command. */
@Nullable
public PumpHistory history;
/** Basal rate profile if requested. */
public BasalProfile basalProfile;
/** Total duration the command took. */
public String duration;
/** Warnings raised on the pump that are forwarded to AAPS to be turned into AAPS
* notifications. */
@ -28,6 +28,7 @@ public class CommandResult {
public int reservoirLevel = -1;
@Nullable
@Deprecated
public Bolus lastBolus;
public CommandResult success(boolean success) {
@ -35,11 +36,6 @@ public class CommandResult {
return this;
}
public CommandResult duration(String duration) {
this.duration = duration;
return this;
}
public CommandResult state(PumpState state) {
this.state = state;
return this;
@ -62,7 +58,6 @@ public class CommandResult {
", state=" + state +
", history=" + history +
", basalProfile=" + basalProfile +
", duration='" + duration + '\'' +
", forwardedWarnings='" + forwardedWarnings + '\'' +
", lastBolus=" + lastBolus +
'}';

View file

@ -14,6 +14,7 @@ import java.util.Objects;
import de.jotomo.ruffy.spi.BolusProgressReporter;
import de.jotomo.ruffy.spi.PumpWarningCodes;
import de.jotomo.ruffy.spi.WarningOrErrorCode;
import de.jotomo.ruffy.spi.history.Bolus;
import de.jotomo.ruffyscripter.RuffyScripter;
import static de.jotomo.ruffy.spi.BolusProgressReporter.State.DELIVERED;
@ -130,7 +131,19 @@ public class BolusCommand extends BaseCommand {
scripter.confirmAlert(PumpWarningCodes.BATTERY_LOW, 2000);
result.forwardedWarnings.add(PumpWarningCodes.BATTERY_LOW);
} else {
throw new CommandException("Pump is showing exotic warning: " + warningCode);
// all other warnings or errors;
// An occlusion error can also occur during bolus. To read the partially delivered
// bolus, we'd have to first confirm the error. But an (occlusion) **error** shall not
// be confirmed and potentially be swallowed by a bug or shaky comms, so we let
// the pump be noisy (which the user will have to interact with anyway).
// Thus, this method will terminate with an exception and display an error message.
// Ideally, sometime after the user has dealt with the situation, the partially
// delivered bolus should be read. However, ready history is tricky at this point.
// Also: with an occlusion, the amount of insulin active is in question.
// It would be safer to assume the delivered bolus results in IOB, but there's
// only so much we can do at this point, so the user shall take over here and
// add a bolus record as and if needed.
throw new CommandException("Pump is showing exotic warning/error: " + warningOrErrorCode);
}
}
if (bolusRemaining != null && !Objects.equals(bolusRemaining, lastBolusReported)) {
@ -152,6 +165,22 @@ public class BolusCommand extends BaseCommand {
// ignore
}
}
if (cancelInProgress) {
// delivery was started, but cancellation requested, so there is a bolus we can read
ReadReservoirLevelAndLastBolus readReservoirLevelAndLastBolus = new ReadReservoirLevelAndLastBolus();
readReservoirLevelAndLastBolus.setScripter(scripter);
readReservoirLevelAndLastBolus.execute();
Bolus lastBolus = readReservoirLevelAndLastBolus.result.lastBolus;
if (Math.abs(System.currentTimeMillis() - lastBolus.timestamp) >= 10 * 60 * 1000) {
throw new CommandException("Unable to determine last bolus");
}
result.delivered = lastBolus.amount;
} else {
// bolus delivery completed successfully and completely
result.delivered = bolus;
}
bolusProgressReporter.report(DELIVERED, 100, bolus);
result.success = true;
} finally {