From a46d1c73ebc896d97c3d5239a0c76db004332245 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 4 Dec 2020 11:49:50 +0100 Subject: [PATCH] - Prevent cancelled TBR from being reported twice - Split TBR after uncertain cancellation in order to only cancel the remaining part when recovering from an uncertain failure --- .../androidaps/db/TemporaryBasal.java | 8 +++- .../definition/PodHistoryEntryType.java | 1 + .../driver/manager/PodStateManager.java | 3 +- .../omnipod/manager/AapsOmnipodManager.java | 40 ++++++++++++++++++- .../command/OmnipodCustomCommandType.java | 3 +- .../pump/omnipod/ui/PodHistoryActivity.java | 4 +- omnipod/src/main/res/values/strings.xml | 1 + 7 files changed, 51 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java index 012016ee03..ee474b0635 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java +++ b/core/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -15,8 +15,8 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.Interval; -import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.interfaces.ProfileFunction; +import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DecimalFormatter; @@ -381,6 +381,12 @@ public class TemporaryBasal implements Interval, DbObjectBase { return (remainingMin < 0) ? 0 : Math.round(remainingMin); } + public int getPlannedRemainingMinutesRoundedUp() { + float remainingMin = (end() - System.currentTimeMillis()) / 1000f / 60; + return (remainingMin < 0) ? 0 : (int) Math.ceil(remainingMin); + } + + public double tempBasalConvertedToAbsolute(long time, Profile profile) { if (isFakeExtended) { return profile.getBasal(time) + netExtendedRate; diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/PodHistoryEntryType.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/PodHistoryEntryType.java index 47b2fd7693..742fb3ce98 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/PodHistoryEntryType.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/PodHistoryEntryType.java @@ -23,6 +23,7 @@ public enum PodHistoryEntryType { CANCEL_TEMPORARY_BASAL(12, R.string.omnipod_cmd_cancel_tbr, PumpHistoryEntryGroup.Basal), SET_FAKE_SUSPENDED_TEMPORARY_BASAL(13, R.string.omnipod_cmd_set_fake_suspended_tbr, PumpHistoryEntryGroup.Basal), CANCEL_FAKE_SUSPENDED_TEMPORARY_BASAL(14, R.string.omnipod_cmd_cancel_fake_suspended_tbr, PumpHistoryEntryGroup.Basal), + SPLIT_TEMPORARY_BASAL(15, R.string.omnipod_cmd_split_tbr, PumpHistoryEntryGroup.Basal), SET_BASAL_SCHEDULE(20, R.string.omnipod_cmd_set_basal_schedule, PumpHistoryEntryGroup.Basal), diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java index 2163e9ffb1..2af4d0734f 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java @@ -428,7 +428,6 @@ public abstract class PodStateManager { setAndStore(() -> { if (!Objects.equals(podState.isTempBasalCertain(), certain)) { podState.setTempBasalCertain(certain); - onTbrChanged(); } }); } @@ -570,7 +569,7 @@ public abstract class PodStateManager { boolean isBasalCertain = podState.isBasalCertain() == null || podState.isBasalCertain(); boolean isTempBasalCertain = podState.isTempBasalCertain() == null || podState.isTempBasalCertain(); - if (!status.getDeliveryStatus().isTbrRunning()) { + if (!status.getDeliveryStatus().isTbrRunning() && hasTempBasal()) { if (isTempBasalCertain) { clearTempBasal(); // Triggers onTbrChanged when appropriate } else { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java index b0ff0ef435..b6cb382a0d 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java @@ -485,6 +485,8 @@ public class AapsOmnipodManager { showNotification(getStringResource(R.string.omnipod_error_set_temp_basal_failed_old_tbr_might_be_cancelled), Notification.URGENT, isNotificationUncertainTbrSoundEnabled() ? R.raw.boluserror : null); + splitActiveTbr(); // Split any active TBR so when we recover from the uncertain TBR status,we only cancel the part after the cancellation + return new PumpEnactResult(injector).success(false).enacted(false).comment(errorMessage); } catch (Exception ex) { String errorMessage = translateException(ex); @@ -520,8 +522,10 @@ public class AapsOmnipodManager { try { executeCommand(() -> delegate.cancelTemporaryBasal(isTbrBeepsEnabled())); } catch (Exception ex) { - if (ex instanceof OmnipodException && !((OmnipodException) ex).isCertainFailure()) { + if (OmnipodManager.isCertainFailure(ex)) { showNotification(getStringResource(R.string.omnipod_error_cancel_temp_basal_failed_uncertain), Notification.URGENT, isNotificationUncertainTbrSoundEnabled() ? R.raw.boluserror : null); + } else { + splitActiveTbr(); // Split any active TBR so when we recover from the uncertain TBR status,we only cancel the part after the cancellation } String errorMessage = translateException(ex); addFailureToHistory(PodHistoryEntryType.CANCEL_TEMPORARY_BASAL, errorMessage); @@ -730,23 +734,55 @@ public class AapsOmnipodManager { } public void reportCancelledTbr() { + reportCancelledTbr(System.currentTimeMillis()); + } + + public void reportCancelledTbr(long time) { aapsLogger.debug(LTag.PUMP, "Reporting cancelled TBR to AAPS"); long pumpId = addSuccessToHistory(PodHistoryEntryType.CANCEL_TEMPORARY_BASAL_BY_DRIVER, null); TemporaryBasal temporaryBasal = new TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // + .date(time) // .duration(0) // .source(Source.PUMP) // .pumpId(pumpId); activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + + sendEvent(new EventRefreshOverview("AapsOmnipodManager.reportCancelledTbr()", false)); } public long addTbrSuccessToHistory(long requestTime, TempBasalPair tempBasalPair) { return addSuccessToHistory(requestTime, PodHistoryEntryType.SET_TEMPORARY_BASAL, tempBasalPair); } + // Cancels current TBR and adds a new TBR for the remaining duration + private void splitActiveTbr() { + TemporaryBasal previouslyRunningTempBasal = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); + if (previouslyRunningTempBasal != null) { + // Cancel the previously running TBR and start a NEW TBR here for the remaining duration, + // so that we only cancel the remaining part when recovering from an uncertain failure in the cancellation + int minutesRemaining = previouslyRunningTempBasal.getPlannedRemainingMinutesRoundedUp(); + + if (minutesRemaining > 0) { + reportCancelledTbr(System.currentTimeMillis() - 1000); + + TempBasalPair newTempBasalPair = new TempBasalPair(previouslyRunningTempBasal.absoluteRate, false, minutesRemaining); + long pumpId = addSuccessToHistory(PodHistoryEntryType.SPLIT_TEMPORARY_BASAL, newTempBasalPair); + + TemporaryBasal tempBasal = new TemporaryBasal(injector) // + .date(System.currentTimeMillis()) // + .absolute(previouslyRunningTempBasal.absoluteRate) + .duration(minutesRemaining) // + .pumpId(pumpId) // + .source(Source.PUMP); + + activePlugin.getActiveTreatments().addToHistoryTempBasal(tempBasal); + } + } + } + private void addTempBasalTreatment(long time, long pumpId, TempBasalPair tempBasalPair) { TemporaryBasal tempStart = new TemporaryBasal(injector) // .date(time) // diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/OmnipodCustomCommandType.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/OmnipodCustomCommandType.java index f5c787be26..f88777638e 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/OmnipodCustomCommandType.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/OmnipodCustomCommandType.java @@ -9,8 +9,7 @@ public enum OmnipodCustomCommandType { DEACTIVATE_POD("DEACTIVATE POD"), HANDLE_TIME_CHANGE("HANDLE TIME CHANGE"), UPDATE_ALERT_CONFIGURATION("UPDATE ALERT CONFIGURATION"), - PLAY_TEST_BEEP("PLAY TEST BEEP") - ; + PLAY_TEST_BEEP("PLAY TEST BEEP"); private final String description; diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java index 74aded32fb..9cc797b375 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java @@ -35,7 +35,6 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil; import info.nightscout.androidaps.plugins.pump.omnipod.R; import info.nightscout.androidaps.plugins.pump.omnipod.definition.PodHistoryEntryType; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType; import info.nightscout.androidaps.plugins.pump.omnipod.util.AapsOmnipodUtil; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -249,7 +248,8 @@ public class PodHistoryActivity extends NoSplashAppCompatActivity { PodHistoryEntryType entryType = PodHistoryEntryType.getByCode(historyEntry.getPodEntryTypeCode()); switch (entryType) { - case SET_TEMPORARY_BASAL: { + case SET_TEMPORARY_BASAL: + case SPLIT_TEMPORARY_BASAL: { TempBasalPair tempBasalPair = aapsOmnipodUtil.getGsonInstance().fromJson(historyEntry.getData(), TempBasalPair.class); valueView.setText(resourceHelper.gs(R.string.omnipod_history_tbr_value, tempBasalPair.getInsulinRate(), tempBasalPair.getDurationMinutes())); } diff --git a/omnipod/src/main/res/values/strings.xml b/omnipod/src/main/res/values/strings.xml index 417b852805..db9697645f 100644 --- a/omnipod/src/main/res/values/strings.xml +++ b/omnipod/src/main/res/values/strings.xml @@ -172,6 +172,7 @@ Read pulse log Set fake temporary basal because the Pod is suspended Cancel fake temporary basal that was created because the Pod was suspended + Split temporary basal because of uncertain failure in cancellation Beep config Play test beep