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 e249c58981..0ea643bad8 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 @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; import java.util.Calendar; import java.util.Date; +import java.util.List; import de.jotomo.ruffy.spi.BasalProfile; import de.jotomo.ruffy.spi.BolusProgressReporter; @@ -39,7 +40,6 @@ 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.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; @@ -47,8 +47,6 @@ import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI; import info.nightscout.utils.DateUtil; -import static de.jotomo.ruffy.spi.BolusProgressReporter.State.FINISHED; - /** * Created by mike on 05.08.2016. */ @@ -457,6 +455,8 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } lastRequestedBolus = new Bolus(System.currentTimeMillis(), detailedBolusInfo.insulin, true); + long pumpTimeAtStartOfCommand = runCommand(null, 1, ruffyScripter::readPumpState).state.pumpTime; + try { pump.activity = MainApp.sResources.getString(R.string.combo_pump_action_bolusing, detailedBolusInfo.insulin); MainApp.bus().post(new EventComboPumpUpdateGUI()); @@ -472,19 +472,20 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf detailedBolusInfo.isSMB ? nullBolusProgressReporter : bolusProgressReporter)); bolusInProgress = false; - if (bolusCmdResult.delivered > 0) { - detailedBolusInfo.insulin = bolusCmdResult.delivered; - detailedBolusInfo.source = Source.USER; - MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + if (bolusCmdResult.success) { + if (bolusCmdResult.delivered > 0) { + detailedBolusInfo.insulin = bolusCmdResult.delivered; + detailedBolusInfo.source = Source.USER; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + } + return new PumpEnactResult() + .success(true) + .enacted(bolusCmdResult.delivered > 0) + .bolusDelivered(bolusCmdResult.delivered) + .carbsDelivered(detailedBolusInfo.carbs); + } else { + return recoverFromErrorDuringBolusDelivery(detailedBolusInfo, pumpTimeAtStartOfCommand); } - - return new PumpEnactResult() - .success(bolusCmdResult.success) - .enacted(bolusCmdResult.delivered > 0) - .bolusDelivered(bolusCmdResult.delivered) - .carbsDelivered(detailedBolusInfo.carbs) - .comment(bolusCmdResult.success ? "" : - MainApp.sResources.getString(R.string.combo_bolus_bolus_delivery_failed)); } finally { pump.activity = null; MainApp.bus().post(new EventComboPumpUpdateGUI()); @@ -493,6 +494,49 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } } + + /** + * If there was an error during BolusCommand the scripter will have reconnected as needed and waited + * for a bolus delivery to complete (once bolus delivery started it continues regardless of a connection loss). + * So, here we are with a connection again, let's read the last bolus record and check if + * its date is >= the time this command started (using the pump's time!). + * If there is such a bolus with <= the requested amount, then it's from this + * command and shall be added to treatments. If the bolus wasn't delivered in full + * add it but raise a warning. Raise a warning as well if no bolus was delivered at all. + */ + private PumpEnactResult recoverFromErrorDuringBolusDelivery(DetailedBolusInfo detailedBolusInfo, long pumpTimeAtStartOfCommand) { + log.debug("Trying to determine from pump history what was actually delivered"); + CommandResult readLastBolusResult = runCommand(MainApp.sResources.getString(R.string.combo_activity_verifying_delivered_bolus), 3, + () -> ruffyScripter.readHistory(new PumpHistoryRequest().bolusHistory(PumpHistoryRequest.LAST))); + List bolusHistory = readLastBolusResult.history.bolusHistory; + Bolus lastBolus = !bolusHistory.isEmpty() ? bolusHistory.get(0) : null; + + if (lastBolus == null // no bolus ever given + || lastBolus.timestamp < pumpTimeAtStartOfCommand // this is not the bolus you're looking for + || !lastBolus.isValid) { // ext/multiwave bolus + log.debug("No bolus was delivered"); + return new PumpEnactResult().success(false).enacted(false) + .comment(MainApp.sResources.getString(R.string.combo_error_no_bolus_delivered)); + } else if (Math.abs(lastBolus.amount - detailedBolusInfo.insulin) > 0.01) { // bolus only partially delivered + detailedBolusInfo.insulin = lastBolus.amount; + detailedBolusInfo.source = Source.USER; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + log.debug(String.format("Added partial bolus of %.2f to treatments", lastBolus.amount)); + return new PumpEnactResult().success(false).enacted(true) + .comment(String.format(MainApp.sResources.getString(R.string.combo_error_partial_bolus_delivered), + lastBolus.amount, detailedBolusInfo.insulin)); + } + + // bolus was correctly and fully delivered + detailedBolusInfo.insulin = lastBolus.amount; + detailedBolusInfo.source = Source.USER; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + log.debug("Added correctly delivered bolus to treatments"); + return new PumpEnactResult().success(true).enacted(true) + .bolusDelivered(lastBolus.amount) + .carbsDelivered(detailedBolusInfo.carbs); + } + @Override public void stopBolusDelivering() { if (bolusInProgress) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fa2f33d6b2..74702bdfd4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -812,7 +812,6 @@ Use system notifications for alerts Never Requested operation not supported by pump - Bolus delivery failed. A (partial) bolus might have been delivered. Please check the pump and the treatments tabs and bolus again as needed. 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. A bolus with the same amount was requested within the last minute. For safety reasons this is disallowed. Now @@ -838,5 +837,8 @@ This will read the full history and state of the pump. Everything in \"My Data\" and the basal rate. Boluses and TBRs will be added to Treatments if they don\'t already exist. This can cause entries to be duplicated because the pump\'s time is imprecise. Using this when normally looping with the pump is highly discouraged and reserved for special circumstances. If you still want to do this, long press this button again.\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided. Are you really sure you want to read all pump data and take the consequences of this action? TBR CANCELLED warning was confirmed + Bolus delivery failed. It appears no bolus was delivered. To be sure, please check the pump to avoid a double bolus and then bolus again. To guard against bugs, boluses are not automatically retried. + Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions. + Verifying delivered bolus