From a2de14a44ab4f1ed82cbaa81b8022ad9fac5296e Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 18:14:38 +0100 Subject: [PATCH 01/27] Prevent 0x31 Pod faults and improve recovery from uncertain delivery statuses --- .../pump/omnipod/OmnipodPumpPlugin.java | 8 +- .../driver/manager/OmnipodManager.java | 82 +++++++++++++++++-- .../driver/manager/PodStateManager.java | 56 ++++++++++--- .../omnipod/ui/OmnipodOverviewFragment.kt | 51 +++++++----- 4 files changed, 153 insertions(+), 44 deletions(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 06b7c963a5..cf21fb7a24 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -506,15 +506,19 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } /** - * The only actual status requests we send to the Pod here are on startup (in {@link #initializeAfterRileyLinkConnection() initializeAfterRileyLinkConnection()}) - * And when the user explicitly requested it by clicking the Refresh button on the Omnipod tab (which is executed through {@link #executeCustomCommand(CustomCommand)}) * We don't do periodical status requests because that could drain the Pod's battery + * The only actual status requests we send to the Pod here are on startup (in {@link #initializeAfterRileyLinkConnection() initializeAfterRileyLinkConnection()}) + * And when the basal and/or temp basal status is uncertain + * When the user explicitly requested it by clicking the Refresh button on the Omnipod tab (which is executed through {@link #executeCustomCommand(CustomCommand)}) */ @Override public void getPumpStatus() { if (firstRun) { initializeAfterRileyLinkConnection(); firstRun = false; + } else if (!podStateManager.isBasalCertain() || !podStateManager.isTempBasalCertain()) { + aapsLogger.info(LTag.PUMP, "Acknowledged AAPS getPumpStatus request because basal and/or temp basal is uncertain"); + executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); } } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java index 7158e9f98d..7ddd6d71b7 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java @@ -171,6 +171,15 @@ public class OmnipodManager { public synchronized void setBasalSchedule(BasalSchedule schedule, boolean acknowledgementBeep) { assertReadyForDelivery(); + if (!podStateManager.isBasalCertain()) { + try { + getPodStatus(); + } catch (OmnipodException ex) { + ex.setCertainFailure(true); + throw ex; + } + } + boolean wasSuspended = podStateManager.isSuspended(); if (!wasSuspended) { try { @@ -185,12 +194,17 @@ public class OmnipodManager { } } + BasalSchedule oldBasalSchedule = podStateManager.getBasalSchedule(); + try { + podStateManager.setBasalSchedule(schedule); + podStateManager.setBasalCertain(false); executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, schedule, false, podStateManager.getScheduleOffset(), acknowledgementBeep))); - podStateManager.setBasalSchedule(schedule); } catch (OmnipodException ex) { if (ex.isCertainFailure()) { + podStateManager.setBasalSchedule(oldBasalSchedule); + podStateManager.setBasalCertain(true); if (!wasSuspended) { throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); } @@ -206,6 +220,19 @@ public class OmnipodManager { public synchronized void setTemporaryBasal(double rate, Duration duration, boolean acknowledgementBeep, boolean completionBeep) { assertReadyForDelivery(); + if (!podStateManager.isTempBasalCertain() || !podStateManager.isBasalCertain()) { + try { + getPodStatus(); + } catch (OmnipodException ex) { + ex.setCertainFailure(true); + throw ex; + } + } + + if (podStateManager.isSuspended()) { + throw new IllegalDeliveryStatusException(DeliveryStatus.NORMAL, DeliveryStatus.SUSPENDED); + } + boolean cancelCurrentTbr = podStateManager.isTempBasalRunning(); if (cancelCurrentTbr) { @@ -217,17 +244,20 @@ public class OmnipodManager { } // Uncertain failure - podStateManager.setTempBasalCertain(false); throw new PrecedingCommandFailedUncertainlyException(ex); } } try { + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration); + podStateManager.setTempBasalCertain(false); executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction( podStateManager, rate, duration, acknowledgementBeep, completionBeep))); - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration); } catch (OmnipodException ex) { if (ex.isCertainFailure()) { + podStateManager.clearTempBasal(); + podStateManager.setTempBasalCertain(true); if (cancelCurrentTbr) { throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); } @@ -235,7 +265,6 @@ public class OmnipodManager { } // Uncertain failure - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, false); throw ex; } } @@ -247,11 +276,33 @@ public class OmnipodManager { private synchronized StatusResponse cancelDelivery(EnumSet deliveryTypes, boolean acknowledgementBeep) { assertReadyForDelivery(); - return executeAndVerify(() -> { - StatusResponse statusResponse = communicationService.executeAction(new CancelDeliveryAction(podStateManager, deliveryTypes, acknowledgementBeep)); - aapsLogger.info(LTag.PUMPCOMM, "Status response after cancel delivery[types={}]: {}", deliveryTypes.toString(), statusResponse.toString()); - return statusResponse; - }); + if (deliveryTypes.contains(DeliveryType.BASAL)) { + podStateManager.setBasalCertain(false); + } + if (deliveryTypes.contains(DeliveryType.TEMP_BASAL)) { + podStateManager.setTempBasalCertain(false); + } + + try { + return executeAndVerify(() -> { + StatusResponse statusResponse; + statusResponse = communicationService.executeAction(new CancelDeliveryAction(podStateManager, deliveryTypes, acknowledgementBeep)); + + aapsLogger.info(LTag.PUMPCOMM, "Status response after cancel delivery[types={}]: {}", deliveryTypes.toString(), statusResponse.toString()); + return statusResponse; + }); + } catch (OmnipodException ex) { + if (ex.isCertainFailure()) { + if (deliveryTypes.contains(DeliveryType.BASAL)) { + podStateManager.setBasalCertain(true); + } + if (deliveryTypes.contains(DeliveryType.TEMP_BASAL)) { + podStateManager.setTempBasalCertain(true); + } + } + + throw ex; + } } // Returns a SingleSubject that returns when the bolus has finished. @@ -260,6 +311,19 @@ public class OmnipodManager { public synchronized BolusCommandResult bolus(Double units, boolean acknowledgementBeep, boolean completionBeep, BiConsumer progressIndicationConsumer) { assertReadyForDelivery(); + if (!podStateManager.isBasalCertain()) { + try { + getPodStatus(); + } catch (OmnipodException ex) { + ex.setCertainFailure(true); + throw ex; + } + } + + if (podStateManager.isSuspended()) { + throw new IllegalDeliveryStatusException(DeliveryStatus.NORMAL, DeliveryStatus.SUSPENDED); + } + bolusCommandExecutionSubject = SingleSubject.create(); CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS; 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 b482cc3a23..fa32c28a20 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 @@ -368,6 +368,14 @@ public abstract class PodStateManager { setAndStore(() -> podState.setBasalSchedule(basalSchedule)); } + public final boolean isBasalCertain() { + return getSafe(() -> podState.isBasalCertain()); + } + + public final void setBasalCertain(boolean certain) { + setAndStore(() -> podState.setBasalCertain(certain)); + } + public final DateTime getLastBolusStartTime() { return getSafe(() -> podState.getLastBolusStartTime()); } @@ -419,11 +427,11 @@ public abstract class PodStateManager { setSafe(() -> podState.setTempBasalCertain(certain)); } - public final void setTempBasal(DateTime startTime, Double amount, Duration duration, boolean certain) { - setTempBasal(startTime, amount, duration, certain, true); + public final void setTempBasal(DateTime startTime, Double amount, Duration duration) { + setTempBasal(startTime, amount, duration, true); } - public final void setTempBasal(DateTime startTime, Double amount, Duration duration, Boolean certain, boolean store) { + private void setTempBasal(DateTime startTime, Double amount, Duration duration, boolean store) { DateTime currentStartTime = getTempBasalStartTime(); Double currentAmount = getTempBasalAmount(); Duration currentDuration = getTempBasalDuration(); @@ -432,7 +440,6 @@ public abstract class PodStateManager { podState.setTempBasalStartTime(startTime); podState.setTempBasalAmount(amount); podState.setTempBasalDuration(duration); - podState.setTempBasalCertain(certain); }; if (store) { @@ -444,6 +451,14 @@ public abstract class PodStateManager { } } + public final void clearTempBasal() { + clearTempBasal(true); + } + + private void clearTempBasal(boolean store) { + setTempBasal(null, null, null, store); + } + /** * @return true when a Temp Basal is stored in the Pod Stated * Please note that this could also be an expired Temp Basal. For an indication on whether or not @@ -457,13 +472,22 @@ public abstract class PodStateManager { * @return true when a Temp Basal is stored in the Pod State and this temp basal is currently running (based on start time and duration) */ public final boolean isTempBasalRunning() { - return isTempBasalRunningAt(DateTime.now()); + return isTempBasalRunningAt(null); } /** - * @return true when a Temp Basal is stored in the Pod State and this temp basal is running at the given time (based on start time and duration) + * @param time the time for which to look up whether a temp basal is running, null meaning now + * @return true when a Temp Basal is stored in the Pod State and this temp basal is running at the given time (based on start time and duration), + * or when the time provided is null and the delivery status of the Pod inidicated that a TBR is running, but not TBR is stored + * This can happen in some rare cases. */ public final boolean isTempBasalRunningAt(DateTime time) { + if (time == null) { // now + if (!hasTempBasal() && getLastDeliveryStatus().isTbrRunning()) { + return true; + } + time = DateTime.now(); + } if (hasTempBasal()) { DateTime tempBasalStartTime = getTempBasalStartTime(); DateTime tempBasalEndTime = tempBasalStartTime.plus(getTempBasalDuration()); @@ -537,15 +561,12 @@ public abstract class PodStateManager { podState.setTotalTicksDelivered(status.getTicksDelivered()); podState.setPodProgressStatus(status.getPodProgressStatus()); podState.setTimeActive(status.getTimeActive()); - if (status.getDeliveryStatus().isTbrRunning()) { - if (!isTempBasalCertain() && isTempBasalRunning()) { - podState.setTempBasalCertain(true); - } - } else { - // Triggers {@link #onTbrChanged() onTbrChanged()} when appropriate - setTempBasal(null, null, null, true, false); + if (!status.getDeliveryStatus().isTbrRunning()) { + clearTempBasal(false); } podState.setLastUpdatedFromResponse(DateTime.now()); + podState.setTempBasalCertain(true); + podState.setBasalCertain(true); if (status instanceof PodInfoDetailedStatus) { PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) status; @@ -667,6 +688,7 @@ public abstract class PodStateManager { private DeliveryStatus lastDeliveryStatus; private AlertSet activeAlerts; private BasalSchedule basalSchedule; + private boolean basalCertain; private DateTime lastBolusStartTime; private Double lastBolusAmount; private Duration lastBolusDuration; @@ -871,6 +893,14 @@ public abstract class PodStateManager { this.basalSchedule = basalSchedule; } + Boolean isBasalCertain() { + return basalCertain; + } + + void setBasalCertain(Boolean certain) { + this.basalCertain = certain; + } + DateTime getLastBolusStartTime() { return lastBolusStartTime; } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt index 3fd3b27472..a0e48f4f91 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt @@ -361,11 +361,17 @@ class OmnipodOverviewFragment : DaggerFragment() { } } else { if (podStateManager.podProgressStatus.isRunning) { - if (podStateManager.isSuspended) { + var status = if (podStateManager.isSuspended) { resourceHelper.gs(R.string.omnipod_pod_status_suspended) } else { resourceHelper.gs(R.string.omnipod_pod_status_running) } + + if (!podStateManager.isBasalCertain) { + status += " (" + resourceHelper.gs(R.string.omnipod_uncertain) + ")" + } + + status } else if (podStateManager.podProgressStatus == PodProgressStatus.FAULT_EVENT_OCCURRED) { resourceHelper.gs(R.string.omnipod_pod_status_pod_fault) } else if (podStateManager.podProgressStatus == PodProgressStatus.INACTIVE) { @@ -375,7 +381,7 @@ class OmnipodOverviewFragment : DaggerFragment() { } } - val podStatusColor = if (!podStateManager.isPodActivationCompleted || podStateManager.isPodDead || podStateManager.isSuspended) { + val podStatusColor = if (!podStateManager.isPodActivationCompleted || podStateManager.isPodDead || podStateManager.isSuspended || (podStateManager.isPodRunning && !podStateManager.isBasalCertain)) { Color.RED } else { Color.WHITE @@ -406,26 +412,31 @@ class OmnipodOverviewFragment : DaggerFragment() { private fun updateTempBasal() { if (podStateManager.isPodActivationCompleted && podStateManager.isTempBasalRunning) { - val now = DateTime.now() - - val startTime = podStateManager.tempBasalStartTime - val amount = podStateManager.tempBasalAmount - val duration = podStateManager.tempBasalDuration - - val minutesRunning = Duration(startTime, now).standardMinutes - - var text: String - val textColor: Int - text = resourceHelper.gs(R.string.omnipod_overview_temp_basal_value, amount, dateUtil.timeString(startTime.millis), minutesRunning, duration.standardMinutes) - if (podStateManager.isTempBasalCertain) { - textColor = Color.WHITE + if (!podStateManager.hasTempBasal()) { + omnipod_overview_temp_basal.text = "???" + omnipod_overview_temp_basal.setTextColor(Color.RED) } else { - textColor = Color.RED - text += " (" + resourceHelper.gs(R.string.omnipod_uncertain) + ")" - } + val now = DateTime.now() - omnipod_overview_temp_basal.text = text - omnipod_overview_temp_basal.setTextColor(textColor) + val startTime = podStateManager.tempBasalStartTime + val amount = podStateManager.tempBasalAmount + val duration = podStateManager.tempBasalDuration + + val minutesRunning = Duration(startTime, now).standardMinutes + + var text: String + val textColor: Int + text = resourceHelper.gs(R.string.omnipod_overview_temp_basal_value, amount, dateUtil.timeString(startTime.millis), minutesRunning, duration.standardMinutes) + if (podStateManager.isTempBasalCertain) { + textColor = Color.WHITE + } else { + textColor = Color.RED + text += " (" + resourceHelper.gs(R.string.omnipod_uncertain) + ")" + } + + omnipod_overview_temp_basal.text = text + omnipod_overview_temp_basal.setTextColor(textColor) + } } else { omnipod_overview_temp_basal.text = PLACEHOLDER omnipod_overview_temp_basal.setTextColor(Color.WHITE) From 084c8fd02f68e9f1eb9d60d8fe926db6658020c5 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 18:21:29 +0100 Subject: [PATCH 02/27] Small fixes --- .../omnipod/driver/manager/OmnipodManager.java | 3 +-- .../pump/omnipod/ui/OmnipodOverviewFragment.kt | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java index 7ddd6d71b7..858186bc7f 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java @@ -249,11 +249,10 @@ public class OmnipodManager { } try { - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration); + podStateManager.setTempBasal(DateTime.now().plus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration); podStateManager.setTempBasalCertain(false); executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction( podStateManager, rate, duration, acknowledgementBeep, completionBeep))); - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration); } catch (OmnipodException ex) { if (ex.isCertainFailure()) { podStateManager.clearTempBasal(); diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt index a0e48f4f91..7916e1a934 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt @@ -438,8 +438,18 @@ class OmnipodOverviewFragment : DaggerFragment() { omnipod_overview_temp_basal.setTextColor(textColor) } } else { - omnipod_overview_temp_basal.text = PLACEHOLDER - omnipod_overview_temp_basal.setTextColor(Color.WHITE) + var text = PLACEHOLDER + val textColor: Int + + if (podStateManager.isTempBasalCertain) { + textColor = Color.WHITE + } else { + textColor = Color.RED + text += " (" + resourceHelper.gs(R.string.omnipod_uncertain) + ")" + } + + omnipod_overview_temp_basal.text = text + omnipod_overview_temp_basal.setTextColor(textColor) } } From 3daff2527e49ea9aedd4ede78cded04c59ce55ac Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 18:49:15 +0100 Subject: [PATCH 03/27] Some more TBR certainty improvements --- .../omnipod/driver/manager/PodStateManager.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) 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 fa32c28a20..70be6b5c1e 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 @@ -424,7 +424,12 @@ public abstract class PodStateManager { } public final void setTempBasalCertain(boolean certain) { - setSafe(() -> podState.setTempBasalCertain(certain)); + setAndStore(() -> { + if (!Objects.equals(podState.isTempBasalCertain(), certain)) { + podState.setTempBasalCertain(certain); + onTbrChanged(); + } + }); } public final void setTempBasal(DateTime startTime, Double amount, Duration duration) { @@ -565,8 +570,13 @@ public abstract class PodStateManager { clearTempBasal(false); } podState.setLastUpdatedFromResponse(DateTime.now()); - podState.setTempBasalCertain(true); - podState.setBasalCertain(true); + if (!podState.isTempBasalCertain()) { + podState.setTempBasalCertain(true); + onTbrChanged(); + } + if (!podState.isBasalCertain()) { + podState.setBasalCertain(true); + } if (status instanceof PodInfoDetailedStatus) { PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) status; From eb37370fd1df8f57f422e9b06bdb87fa00788546 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 19:36:46 +0100 Subject: [PATCH 04/27] Attempt to cancel Omnipod TBR when AAPS is not aware of a TBR --- .../pump/omnipod/OmnipodPumpPlugin.java | 38 ++++++++++++++++--- omnipod/src/main/res/values/strings.xml | 2 + 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index cf21fb7a24..77655d3cc0 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -518,10 +518,32 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, firstRun = false; } else if (!podStateManager.isBasalCertain() || !podStateManager.isTempBasalCertain()) { aapsLogger.info(LTag.PUMP, "Acknowledged AAPS getPumpStatus request because basal and/or temp basal is uncertain"); - executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); + getPodStatus(); } } + private PumpEnactResult getPodStatus() { + PumpEnactResult result = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); + + // bit hacky... + if (result.success && !activePlugin.getActiveTreatments().isTempBasalInProgress() && podStateManager.isTempBasalRunning()) { + aapsLogger.warn(LTag.PUMP, "Cancelling TBR because AAPS is not aware of any running TBR"); + + getCommandQueue().cancelTempBasal(true, new Callback() { + @Override public void run() { + if (result.success) { + aapsLogger.info(LTag.PUMP, "Successfully cancelled TBR because AAPS was not aware of any running TBR"); + } else { + aapsLogger.error(LTag.PUMP, "Failed to cancel TBR because AAPS was not aware of any running TBR"); + rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); + } + } + }); + } + + return result; + } + @NonNull @Override public PumpEnactResult setNewBasalProfile(Profile profile) { @@ -785,7 +807,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, case ACKNOWLEDGE_ALERTS: return executeCommand(OmnipodCommandType.ACKNOWLEDGE_ALERTS, aapsOmnipodManager::acknowledgeAlerts); case GET_POD_STATUS: - return executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); + return getPodStatus(); case READ_PULSE_LOG: return retrievePulseLog(); case SUSPEND_DELIVERY: @@ -861,7 +883,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } else { // Even if automatically changing the time is disabled, we still want to at least do a GetStatus request, // in order to update the Pod's activation time, which we need for calculating the time on the Pod - result = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); + result = getPodStatus(); } if (result.success) { @@ -992,15 +1014,19 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, private void initializeAfterRileyLinkConnection() { if (podStateManager.getActivationProgress().isAtLeast(ActivationProgress.PAIRING_COMPLETED)) { + boolean success = true; for (int i = 0; STARTUP_STATUS_REQUEST_TRIES > i; i++) { - PumpEnactResult result = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); + PumpEnactResult result = getPodStatus(); if (result.success) { + success = true; aapsLogger.debug(LTag.PUMP, "Successfully retrieved Pod status on startup"); break; - } else { - aapsLogger.warn(LTag.PUMP, "Failed to retrieve Pod status on startup"); } } + if (!success) { + aapsLogger.warn(LTag.PUMP, "Failed to retrieve Pod status on startup"); + rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_failed_to_refresh_status_on_startup), Notification.NORMAL))); + } } else { aapsLogger.debug(LTag.PUMP, "Not retrieving Pod status on startup: no Pod running"); } diff --git a/omnipod/src/main/res/values/strings.xml b/omnipod/src/main/res/values/strings.xml index 6cfea07b2b..8370269beb 100644 --- a/omnipod/src/main/res/values/strings.xml +++ b/omnipod/src/main/res/values/strings.xml @@ -122,6 +122,7 @@ Unknown custom command: %1$s Failed to read Pulse Log Failed to refresh status + Failed to refresh status on startup Failed to acknowledge alerts Failed to suspend delivery Failed to set time @@ -135,6 +136,7 @@ The Pod\'s activation time has been exceeded. This Pod can no longer be activated. Failed to verify activation progress. Please retry. Pod suspended + A temporary basal is running on the Pod, but AAPS is unaware of this temp basal. Please cancel your temporary basal. Confirmation From dba9fa7a73a31185b12072e382f729fd6145ef60 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 20:15:17 +0100 Subject: [PATCH 05/27] Register running TBR to AAPS instead of cancelling it on the Pod whenever possible --- .../pump/omnipod/OmnipodPumpPlugin.java | 38 ++++++++++++++----- .../omnipod/manager/AapsOmnipodManager.java | 4 ++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 77655d3cc0..c3f371e592 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -33,6 +33,7 @@ import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppInitialized; @@ -527,18 +528,35 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, // bit hacky... if (result.success && !activePlugin.getActiveTreatments().isTempBasalInProgress() && podStateManager.isTempBasalRunning()) { - aapsLogger.warn(LTag.PUMP, "Cancelling TBR because AAPS is not aware of any running TBR"); + if (podStateManager.hasTempBasal()) { + aapsLogger.warn(LTag.PUMP, "Registering TBR that AAPS was unaware of"); - getCommandQueue().cancelTempBasal(true, new Callback() { - @Override public void run() { - if (result.success) { - aapsLogger.info(LTag.PUMP, "Successfully cancelled TBR because AAPS was not aware of any running TBR"); - } else { - aapsLogger.error(LTag.PUMP, "Failed to cancel TBR because AAPS was not aware of any running TBR"); - rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); + long pumpId = aapsOmnipodManager.addTbrSuccessToHistory(podStateManager.getTempBasalStartTime().getMillis(), + new TempBasalPair(podStateManager.getTempBasalAmount(), false, (int) podStateManager.getTempBasalDuration().getStandardMinutes())); + + TemporaryBasal temporaryBasal = new TemporaryBasal(getInjector()) // + .absolute(podStateManager.getTempBasalAmount()) // + .duration((int) podStateManager.getTempBasalDuration().getStandardMinutes()) + .date(podStateManager.getTempBasalStartTime().getMillis()) // + .source(Source.PUMP) // + .pumpId(pumpId); + + activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + } else { + // Not sure what's going on. Cancel TBR on the Pod + aapsLogger.warn(LTag.PUMP, "Cancelling TBR because AAPS is not aware of any running TBR"); + + getCommandQueue().cancelTempBasal(true, new Callback() { + @Override public void run() { + if (result.success) { + aapsLogger.info(LTag.PUMP, "Successfully cancelled TBR because AAPS was not aware of any running TBR"); + } else { + aapsLogger.error(LTag.PUMP, "Failed to cancel TBR because AAPS was not aware of any running TBR"); + rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); + } } - } - }); + }); + } } return result; 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 fec5c84cac..7eadeb8686 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 @@ -710,6 +710,10 @@ public class AapsOmnipodManager { activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); } + public long addTbrSuccessToHistory(long requestTime, TempBasalPair tempBasalPair) { + return addSuccessToHistory(requestTime, PodHistoryEntryType.SET_TEMPORARY_BASAL, tempBasalPair); + } + private void addTempBasalTreatment(long time, long pumpId, TempBasalPair tempBasalPair) { TemporaryBasal tempStart = new TemporaryBasal(injector) // .date(time) // From 88fbacf0365ca065f5102ea38a7e1918c12ac4dd Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 20:33:01 +0100 Subject: [PATCH 06/27] Actually cancel TBR --- .../pump/omnipod/OmnipodPumpPlugin.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index c3f371e592..976db6a168 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -524,10 +524,10 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } private PumpEnactResult getPodStatus() { - PumpEnactResult result = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); + PumpEnactResult getStatusResult = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); // bit hacky... - if (result.success && !activePlugin.getActiveTreatments().isTempBasalInProgress() && podStateManager.isTempBasalRunning()) { + if (getStatusResult.success && !activePlugin.getActiveTreatments().isTempBasalInProgress() && podStateManager.isTempBasalRunning()) { if (podStateManager.hasTempBasal()) { aapsLogger.warn(LTag.PUMP, "Registering TBR that AAPS was unaware of"); @@ -546,20 +546,17 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, // Not sure what's going on. Cancel TBR on the Pod aapsLogger.warn(LTag.PUMP, "Cancelling TBR because AAPS is not aware of any running TBR"); - getCommandQueue().cancelTempBasal(true, new Callback() { - @Override public void run() { - if (result.success) { - aapsLogger.info(LTag.PUMP, "Successfully cancelled TBR because AAPS was not aware of any running TBR"); - } else { - aapsLogger.error(LTag.PUMP, "Failed to cancel TBR because AAPS was not aware of any running TBR"); - rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); - } - } - }); + PumpEnactResult cancelTbrResult = executeCommand(OmnipodCommandType.CANCEL_TEMPORARY_BASAL, aapsOmnipodManager::cancelTemporaryBasal); + if (cancelTbrResult.success) { + aapsLogger.info(LTag.PUMP, "Successfully cancelled TBR because AAPS was not aware of any running TBR"); + } else { + aapsLogger.error(LTag.PUMP, "Failed to cancel TBR because AAPS was not aware of any running TBR"); + rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); + } } } - return result; + return getStatusResult; } @NonNull From a15eaf6efbcabbe923e0afa6095eef61af5a0162 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Thu, 19 Nov 2020 20:43:13 +0100 Subject: [PATCH 07/27] Nit in translation --- omnipod/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod/src/main/res/values/strings.xml b/omnipod/src/main/res/values/strings.xml index 8370269beb..476fa0a684 100644 --- a/omnipod/src/main/res/values/strings.xml +++ b/omnipod/src/main/res/values/strings.xml @@ -136,7 +136,7 @@ The Pod\'s activation time has been exceeded. This Pod can no longer be activated. Failed to verify activation progress. Please retry. Pod suspended - A temporary basal is running on the Pod, but AAPS is unaware of this temp basal. Please cancel your temporary basal. + A temporary basal is running on the Pod, but AAPS is unaware of this temporary basal. Please cancel your temporary basal manually. Confirmation From f0765a6704990dae96a70e5a0559d5fc1b6ee412 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 20 Nov 2020 18:06:18 +0100 Subject: [PATCH 08/27] Technical improvements on Omnipod uncertain TBR recovery --- .../pump/omnipod/OmnipodPumpPlugin.java | 103 ++++++++++-------- .../driver/manager/PodStateManager.java | 19 +++- .../EventOmnipodUncertainTbrRecovered.kt | 8 ++ .../omnipod/manager/AapsPodStateManager.java | 5 + 4 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodUncertainTbrRecovered.kt diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 976db6a168..369c40f8e9 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -83,6 +83,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodActiveA import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodFaultEventChanged; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodTbrChanged; +import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodUncertainTbrRecovered; import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.CommandAcknowledgeAlerts; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.CommandHandleTimeChange; @@ -155,6 +156,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, private final Handler loopHandler = new Handler(Looper.getMainLooper()); private final Runnable statusChecker; + private boolean isSetTempBasalRunning; private boolean isCancelTempBasalRunning; @Inject @@ -286,7 +288,12 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, disposables.add(rxBus .toObservable(EventOmnipodTbrChanged.class) .observeOn(Schedulers.io()) - .subscribe(event -> updateAapsTbr(), fabricPrivacy::logException) + .subscribe(event -> handleCancelledTbr(), fabricPrivacy::logException) + ); + disposables.add(rxBus + .toObservable(EventOmnipodUncertainTbrRecovered.class) + .observeOn(Schedulers.io()) + .subscribe(event -> handleUncertainTbrRecovery(), fabricPrivacy::logException) ); disposables.add(rxBus .toObservable(EventOmnipodActiveAlertsChanged.class) @@ -351,17 +358,49 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, return rileyLinkServiceData.rileyLinkServiceState.isReady(); } - private void updateAapsTbr() { - // As per the characteristics of the Omnipod, we only know whether or not a TBR is currently active - // But it doesn't tell us the duration or amount, so we can only update TBR status in AAPS if - // The pod is not running a TBR, while AAPS thinks it is - if (!podStateManager.isTempBasalRunning()) { - // Only report TBR cancellations if they haven't been explicitly requested - if (!isCancelTempBasalRunning) { - if (activePlugin.getActiveTreatments().isTempBasalInProgress() && !aapsOmnipodManager.hasSuspendedFakeTbr()) { - aapsOmnipodManager.reportCancelledTbr(); - } + private void handleCancelledTbr() { + // Only report TBR cancellations if they haven't been explicitly requested + if (isCancelTempBasalRunning) { + return; + } + if (!podStateManager.isTempBasalRunning() && activePlugin.getActiveTreatments().isTempBasalInProgress() && !aapsOmnipodManager.hasSuspendedFakeTbr()) { + aapsOmnipodManager.reportCancelledTbr(); + } + } + + private void handleUncertainTbrRecovery() { + // Ignore changes in certainty during tbr commands; these are normal + if (isSetTempBasalRunning || isCancelTempBasalRunning) { + return; + } + + TemporaryBasal tempBasal = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); + + if (podStateManager.isTempBasalRunning() && tempBasal == null) { + if (podStateManager.hasTempBasal()) { + aapsLogger.warn(LTag.PUMP, "Registering TBR that AAPS was unaware of"); + long pumpId = aapsOmnipodManager.addTbrSuccessToHistory(podStateManager.getTempBasalStartTime().getMillis(), + new TempBasalPair(podStateManager.getTempBasalAmount(), false, (int) podStateManager.getTempBasalDuration().getStandardMinutes())); + + TemporaryBasal temporaryBasal = new TemporaryBasal(getInjector()) // + .absolute(podStateManager.getTempBasalAmount()) // + .duration((int) podStateManager.getTempBasalDuration().getStandardMinutes()) + .date(podStateManager.getTempBasalStartTime().getMillis()) // + .source(Source.PUMP) // + .pumpId(pumpId); + + activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); + } else { + // Not sure what's going on. Notify the user + aapsLogger.error(LTag.PUMP, "Unknown TBR in both Pod state and AAPS"); + rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); } + } else if (!podStateManager.isTempBasalRunning() && tempBasal != null) { + aapsLogger.warn(LTag.PUMP, "Invalidating AAPS TBR that actually hadn't succeeded"); + + tempBasal.isValid = false; + activePlugin.getActiveTreatments().addToHistoryTempBasal(tempBasal); + handleCancelledTbr(); } } @@ -524,39 +563,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } private PumpEnactResult getPodStatus() { - PumpEnactResult getStatusResult = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); - - // bit hacky... - if (getStatusResult.success && !activePlugin.getActiveTreatments().isTempBasalInProgress() && podStateManager.isTempBasalRunning()) { - if (podStateManager.hasTempBasal()) { - aapsLogger.warn(LTag.PUMP, "Registering TBR that AAPS was unaware of"); - - long pumpId = aapsOmnipodManager.addTbrSuccessToHistory(podStateManager.getTempBasalStartTime().getMillis(), - new TempBasalPair(podStateManager.getTempBasalAmount(), false, (int) podStateManager.getTempBasalDuration().getStandardMinutes())); - - TemporaryBasal temporaryBasal = new TemporaryBasal(getInjector()) // - .absolute(podStateManager.getTempBasalAmount()) // - .duration((int) podStateManager.getTempBasalDuration().getStandardMinutes()) - .date(podStateManager.getTempBasalStartTime().getMillis()) // - .source(Source.PUMP) // - .pumpId(pumpId); - - activePlugin.getActiveTreatments().addToHistoryTempBasal(temporaryBasal); - } else { - // Not sure what's going on. Cancel TBR on the Pod - aapsLogger.warn(LTag.PUMP, "Cancelling TBR because AAPS is not aware of any running TBR"); - - PumpEnactResult cancelTbrResult = executeCommand(OmnipodCommandType.CANCEL_TEMPORARY_BASAL, aapsOmnipodManager::cancelTemporaryBasal); - if (cancelTbrResult.success) { - aapsLogger.info(LTag.PUMP, "Successfully cancelled TBR because AAPS was not aware of any running TBR"); - } else { - aapsLogger.error(LTag.PUMP, "Failed to cancel TBR because AAPS was not aware of any running TBR"); - rxBus.send(new EventNewNotification(new Notification(Notification.OMNIPOD_PUMP_ALARM, resourceHelper.gs(R.string.omnipod_error_tbr_running_but_aaps_not_aware), Notification.NORMAL).sound(R.raw.boluserror))); - } - } - } - - return getStatusResult; + return executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); } @NonNull @@ -661,7 +668,13 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } } - PumpEnactResult result = executeCommand(OmnipodCommandType.SET_TEMPORARY_BASAL, () -> aapsOmnipodManager.setTemporaryBasal(new TempBasalPair(absoluteRate, false, durationInMinutes))); + isSetTempBasalRunning = true; + PumpEnactResult result; + try { + result = executeCommand(OmnipodCommandType.SET_TEMPORARY_BASAL, () -> aapsOmnipodManager.setTemporaryBasal(new TempBasalPair(absoluteRate, false, durationInMinutes))); + } finally { + isSetTempBasalRunning = false; + } aapsLogger.info(LTag.PUMP, "setTempBasalAbsolute - setTBR. Response: " + result.success); 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 70be6b5c1e..d3519fd392 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 @@ -567,12 +567,18 @@ public abstract class PodStateManager { podState.setPodProgressStatus(status.getPodProgressStatus()); podState.setTimeActive(status.getTimeActive()); if (!status.getDeliveryStatus().isTbrRunning()) { - clearTempBasal(false); + if (podState.isTempBasalCertain()) { + clearTempBasal(); // Triggers onTbrChanged when appropriate + } else { + // Don't trigger onTbrChanged as we will trigger onUncertainTbrRecovered below + podState.setTempBasalStartTime(null); + podState.setTempBasalAmount(null); + podState.setTempBasalDuration(null); + } } - podState.setLastUpdatedFromResponse(DateTime.now()); if (!podState.isTempBasalCertain()) { podState.setTempBasalCertain(true); - onTbrChanged(); + onUncertainTbrRecovered(); } if (!podState.isBasalCertain()) { podState.setBasalCertain(true); @@ -587,6 +593,8 @@ public abstract class PodStateManager { } } } + + podState.setLastUpdatedFromResponse(DateTime.now()); }); } @@ -595,6 +603,11 @@ public abstract class PodStateManager { // Can be overridden in subclasses } + protected void onUncertainTbrRecovered() { + // Deliberately left empty + // Can be overridden in subclasses + } + protected void onActiveAlertsChanged() { // Deliberately left empty // Can be overridden in subclasses diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodUncertainTbrRecovered.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodUncertainTbrRecovered.kt new file mode 100644 index 0000000000..f2c4dc855a --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodUncertainTbrRecovered.kt @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.event + +import info.nightscout.androidaps.events.Event + +/** + * Created by andy on 04.06.2018. + */ +class EventOmnipodUncertainTbrRecovered : Event() \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsPodStateManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsPodStateManager.java index 551206190f..6ebaa1d3b9 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsPodStateManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsPodStateManager.java @@ -10,6 +10,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateMa import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodActiveAlertsChanged; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodFaultEventChanged; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodTbrChanged; +import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodUncertainTbrRecovered; import info.nightscout.androidaps.utils.sharedPreferences.SP; @Singleton @@ -34,6 +35,10 @@ public class AapsPodStateManager extends PodStateManager { sp.putString(OmnipodStorageKeys.Preferences.POD_STATE, podState); } + @Override protected void onUncertainTbrRecovered() { + rxBus.send(new EventOmnipodUncertainTbrRecovered()); + } + @Override protected void onTbrChanged() { rxBus.send(new EventOmnipodTbrChanged()); } From 1eedf86fa1f64ea04146627b32766c3ef0b9071d Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 20 Nov 2020 19:10:21 +0100 Subject: [PATCH 09/27] Use error dialog instead of notification for user-enacted boluses --- .../omnipod/manager/AapsOmnipodManager.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) 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 7eadeb8686..f430dcca4e 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 @@ -1,5 +1,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.manager; +import android.content.Context; +import android.content.Intent; + import org.joda.time.DateTime; import org.joda.time.Duration; import org.json.JSONException; @@ -14,6 +17,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import dagger.android.HasAndroidInjector; +import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; @@ -102,6 +106,7 @@ public class AapsOmnipodManager { private final OmnipodAlertUtil omnipodAlertUtil; private final NSUpload nsUpload; private final ProfileFunction profileFunction; + private final Context context; private boolean basalBeepsEnabled; private boolean bolusBeepsEnabled; @@ -128,8 +133,9 @@ public class AapsOmnipodManager { DatabaseHelperInterface databaseHelper, OmnipodAlertUtil omnipodAlertUtil, NSUpload nsUpload, - ProfileFunction profileFunction - ) { + ProfileFunction profileFunction, + Context context) { + this.podStateManager = podStateManager; this.aapsOmnipodUtil = aapsOmnipodUtil; this.aapsLogger = aapsLogger; @@ -142,6 +148,7 @@ public class AapsOmnipodManager { this.omnipodAlertUtil = omnipodAlertUtil; this.nsUpload = nsUpload; this.profileFunction = profileFunction; + this.context = context; delegate = new OmnipodManager(aapsLogger, communicationService, podStateManager); @@ -357,7 +364,7 @@ public class AapsOmnipodManager { if (detailedBolusInfo.isSMB) { showNotification(getStringResource(R.string.omnipod_error_bolus_failed_uncertain_smb, detailedBolusInfo.insulin), Notification.URGENT, isNotificationUncertainSmbSoundEnabled() ? R.raw.boluserror : null); } else { - showNotification(getStringResource(R.string.omnipod_error_bolus_failed_uncertain), Notification.URGENT, isNotificationUncertainBolusSoundEnabled() ? R.raw.boluserror : null); + showErrorDialog(getStringResource(R.string.omnipod_error_bolus_failed_uncertain), isNotificationUncertainBolusSoundEnabled() ? R.raw.boluserror : null); } } @@ -854,6 +861,15 @@ public class AapsOmnipodManager { rxBus.send(event); } + private void showErrorDialog(String message, Integer sound) { + Intent intent = new Intent(context, ErrorHelperActivity.class); + intent.putExtra("soundid", sound); + intent.putExtra("status", message); + intent.putExtra("title", resourceHelper.gs(R.string.error)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + private void showPodFaultNotification(FaultEventCode faultEventCode) { showPodFaultNotification(faultEventCode, R.raw.boluserror); } From 90387a052d03b507da3cd59337930ee95c6e14f9 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 20 Nov 2020 20:27:09 +0100 Subject: [PATCH 10/27] Prevent NPE --- .../plugins/pump/omnipod/driver/manager/PodStateManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 d3519fd392..e92476d66a 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 @@ -369,7 +369,8 @@ public abstract class PodStateManager { } public final boolean isBasalCertain() { - return getSafe(() -> podState.isBasalCertain()); + Boolean certain = getSafe(() -> podState.isBasalCertain()); + return certain == null || certain; } public final void setBasalCertain(boolean certain) { @@ -711,7 +712,7 @@ public abstract class PodStateManager { private DeliveryStatus lastDeliveryStatus; private AlertSet activeAlerts; private BasalSchedule basalSchedule; - private boolean basalCertain; + private Boolean basalCertain; private DateTime lastBolusStartTime; private Double lastBolusAmount; private Duration lastBolusDuration; From 3c95bb11ced9b0bcd6bd6764607dd722c1d41cb1 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 20 Nov 2020 21:04:42 +0100 Subject: [PATCH 11/27] Prevent crash in Omnipod fragment when no Pod is attached --- .../plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt index 7916e1a934..707a133a6f 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt @@ -441,7 +441,7 @@ class OmnipodOverviewFragment : DaggerFragment() { var text = PLACEHOLDER val textColor: Int - if (podStateManager.isTempBasalCertain) { + if (!podStateManager.isPodActivationCompleted || podStateManager.isTempBasalCertain) { textColor = Color.WHITE } else { textColor = Color.RED From 52a01b0a81a53645fe2b9405267ccdfd0af8815c Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 20 Nov 2020 21:22:10 +0100 Subject: [PATCH 12/27] Bugfix --- .../androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 369c40f8e9..d5658c691f 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -1042,7 +1042,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, private void initializeAfterRileyLinkConnection() { if (podStateManager.getActivationProgress().isAtLeast(ActivationProgress.PAIRING_COMPLETED)) { - boolean success = true; + boolean success = false; for (int i = 0; STARTUP_STATUS_REQUEST_TRIES > i; i++) { PumpEnactResult result = getPodStatus(); if (result.success) { From cab349dd0a06affcf1c8e07b38fee43c4a466db1 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Fri, 20 Nov 2020 22:16:15 +0100 Subject: [PATCH 13/27] Prevent NPE during Pod activation --- .../pump/omnipod/driver/manager/PodStateManager.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 e92476d66a..2163e9ffb1 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 @@ -567,8 +567,11 @@ public abstract class PodStateManager { podState.setTotalTicksDelivered(status.getTicksDelivered()); podState.setPodProgressStatus(status.getPodProgressStatus()); podState.setTimeActive(status.getTimeActive()); + + boolean isBasalCertain = podState.isBasalCertain() == null || podState.isBasalCertain(); + boolean isTempBasalCertain = podState.isTempBasalCertain() == null || podState.isTempBasalCertain(); if (!status.getDeliveryStatus().isTbrRunning()) { - if (podState.isTempBasalCertain()) { + if (isTempBasalCertain) { clearTempBasal(); // Triggers onTbrChanged when appropriate } else { // Don't trigger onTbrChanged as we will trigger onUncertainTbrRecovered below @@ -577,11 +580,11 @@ public abstract class PodStateManager { podState.setTempBasalDuration(null); } } - if (!podState.isTempBasalCertain()) { + if (!isTempBasalCertain) { podState.setTempBasalCertain(true); onUncertainTbrRecovered(); } - if (!podState.isBasalCertain()) { + if (!isBasalCertain) { podState.setBasalCertain(true); } From 86d6fbc615938f6280004578b411f78d48185cc0 Mon Sep 17 00:00:00 2001 From: Artiom Kenibasov Date: Sat, 21 Nov 2020 15:44:32 +0100 Subject: [PATCH 14/27] Added play test beep mechanism --- .../pump/omnipod/OmnipodPumpPlugin.java | 4 ++ .../definition/OmnipodCommandType.java | 3 +- .../definition/PodHistoryEntryType.java | 2 + .../action/ConfigureBeepAction.java | 49 +++++++++++++++++++ .../message/command/BeepConfigCommand.java | 4 -- .../driver/manager/OmnipodManager.java | 19 +++++++ .../omnipod/manager/AapsOmnipodManager.java | 16 ++++++ .../queue/command/CommandPlayTestBeep.java | 16 ++++++ .../command/OmnipodCustomCommandType.java | 4 +- .../pump/omnipod/ui/PodHistoryActivity.java | 7 +++ omnipod/src/main/res/values/strings.xml | 2 + 11 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/ConfigureBeepAction.java create mode 100644 omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/CommandPlayTestBeep.java diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 06b7c963a5..c7afc04cf1 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -76,6 +76,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.util.TimeUtil; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodActiveAlertsChanged; @@ -85,6 +86,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodTbrChan import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.CommandAcknowledgeAlerts; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.CommandHandleTimeChange; +import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.CommandPlayTestBeep; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.CommandUpdateAlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.OmnipodCustomCommand; import info.nightscout.androidaps.plugins.pump.omnipod.queue.command.OmnipodCustomCommandType; @@ -794,6 +796,8 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, return handleTimeChange(((CommandHandleTimeChange) command).isRequestedByUser()); case UPDATE_ALERT_CONFIGURATION: return updateAlertConfiguration(); + case PLAY_TEST_BEEP: + return executeCommand(OmnipodCommandType.PLAY_TEST_BEEP, () -> aapsOmnipodManager.playTestBeep(((CommandPlayTestBeep)command).getBeepType())); default: aapsLogger.warn(LTag.PUMP, "Unknown custom command: " + commandType); return new PumpEnactResult(getInjector()).success(false).enacted(false).comment(resourceHelper.gs(R.string.omnipod_error_unknown_custom_command, commandType)); diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodCommandType.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodCommandType.java index 8d9b250ac4..7cbc3c8a11 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodCommandType.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodCommandType.java @@ -21,7 +21,8 @@ public enum OmnipodCommandType { ACKNOWLEDGE_ALERTS(R.string.omnipod_cmd_acknowledge_alerts), // READ_POD_PULSE_LOG(R.string.omnipod_cmd_read_pulse_log), // SUSPEND_DELIVERY(R.string.omnipod_cmd_suspend_delivery), - RESUME_DELIVERY(R.string.omnipod_cmd_resume_delivery); + RESUME_DELIVERY(R.string.omnipod_cmd_resume_delivery), + PLAY_TEST_BEEP(R.string.omnipod_cmd_play_test_beep); private int resourceId; 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 89560786e0..366e675b20 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 @@ -35,12 +35,14 @@ public enum PodHistoryEntryType { CONFIGURE_ALERTS(50, R.string.omnipod_cmd_configure_alerts, PumpHistoryEntryGroup.Alarm), ACKNOWLEDGE_ALERTS(51, R.string.omnipod_cmd_acknowledge_alerts, PumpHistoryEntryGroup.Alarm), + PLAY_TEST_BEEP(52, R.string.omnipod_cmd_play_test_beep, PumpHistoryEntryGroup.Alarm), SUSPEND_DELIVERY(60, R.string.omnipod_cmd_suspend_delivery, PumpHistoryEntryGroup.Basal), RESUME_DELIVERY(61, R.string.omnipod_cmd_resume_delivery, PumpHistoryEntryGroup.Basal), UNKNOWN_ENTRY_TYPE(99, R.string.omnipod_cmd_unknown_entry); + private int code; private static final Map instanceMap; diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/ConfigureBeepAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/ConfigureBeepAction.java new file mode 100644 index 0000000000..f75c2b652c --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/ConfigureBeepAction.java @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action; + +import org.joda.time.Duration; + +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.BeepConfigCommand; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; +import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; + +public class ConfigureBeepAction implements OmnipodAction { + private final PodStateManager podStateManager; + private final BeepConfigType beepType; + private final boolean basalCompletionBeep; + private final Duration basalIntervalBeep; + private final boolean tempBasalCompletionBeep; + private final Duration tempBasalIntervalBeep; + private final boolean bolusCompletionBeep; + private final Duration bolusIntervalBeep; + + public ConfigureBeepAction(PodStateManager podState, BeepConfigType beepType, boolean basalCompletionBeep, Duration basalIntervalBeep, boolean tempBasalCompletionBeep, Duration tempBasalIntervalBeep, boolean bolusCompletionBeep, Duration bolusIntervalBeep) { + if (podState == null || beepType == null) { + throw new IllegalArgumentException("Pod state manager cannot be null"); + } + + this.beepType = beepType; + this.basalCompletionBeep = basalCompletionBeep; + this.basalIntervalBeep = basalIntervalBeep; + this.tempBasalCompletionBeep = tempBasalCompletionBeep; + this.tempBasalIntervalBeep = tempBasalIntervalBeep; + this.bolusCompletionBeep = bolusCompletionBeep; + this.bolusIntervalBeep = bolusIntervalBeep; + this.podStateManager = podState; + } + + + public ConfigureBeepAction(PodStateManager podState, BeepConfigType beepType) { + this(podState, beepType, false, Duration.ZERO, false, Duration.ZERO, false, Duration.ZERO); + } + + @Override + public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { + return communicationService.sendCommand( + StatusResponse.class, podStateManager + , new BeepConfigCommand(beepType, basalCompletionBeep, basalIntervalBeep, + tempBasalCompletionBeep, tempBasalIntervalBeep, + bolusCompletionBeep, bolusIntervalBeep)); + } +} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/BeepConfigCommand.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/BeepConfigCommand.java index fc36e68eab..47cf4533ba 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/BeepConfigCommand.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/BeepConfigCommand.java @@ -30,10 +30,6 @@ public class BeepConfigCommand extends MessageBlock { encode(); } - public BeepConfigCommand(BeepConfigType beepType) { - this(beepType, false, Duration.ZERO, false, Duration.ZERO, false, Duration.ZERO); - } - private void encode() { encodedData = new byte[]{beepType.getValue()}; encodedData = ByteUtil.concat(encodedData, (byte) ((basalCompletionBeep ? (1 << 6) : 0) + (basalIntervalBeep.getStandardMinutes() & 0x3f))); diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java index 7158e9f98d..d4cf973d15 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java @@ -18,6 +18,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.acti import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.BolusAction; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.CancelDeliveryAction; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.ConfigureAlertsAction; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.ConfigureBeepAction; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.DeactivatePodAction; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.GetPodInfoAction; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.GetStatusAction; @@ -33,6 +34,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType; @@ -427,6 +429,23 @@ public class OmnipodManager { podStateManager.discardState(); } + public synchronized void configureBeeps(BeepConfigType beepType, boolean basalCompletionBeep, Duration basalIntervalBeep, + boolean tempBasalCompletionBeep, Duration tempBasalIntervalBeep, + boolean bolusCompletionBeep, Duration bolusIntervalBeep) { + if (!podStateManager.isPodInitialized()) { + throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, null); + } + communicationService.executeAction(new ConfigureBeepAction(podStateManager, beepType, false, Duration.ZERO, false, Duration.ZERO, false, Duration.ZERO)); + } + + public synchronized void playTestBeep(BeepConfigType beepType) { + if (!podStateManager.isPodInitialized()) { + throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, null); + } + communicationService.executeAction(new ConfigureBeepAction(podStateManager, beepType)); + } + + public OmnipodRileyLinkCommunicationManager getCommunicationService() { return communicationService; } 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 fec5c84cac..9f5333330c 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 @@ -46,6 +46,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; @@ -232,6 +233,21 @@ public class AapsOmnipodManager { return new PumpEnactResult(injector).success(true).enacted(false); } + public PumpEnactResult playTestBeep(BeepConfigType beepType) { + try { + executeCommand(() -> delegate.playTestBeep(beepType)); + } catch (Exception ex) { + String errorMessage = translateException(ex); + addFailureToHistory(PodHistoryEntryType.PLAY_TEST_BEEP, errorMessage); + return new PumpEnactResult(injector).success(false).enacted(false).comment(errorMessage); + } + + addSuccessToHistory(PodHistoryEntryType.PLAY_TEST_BEEP, beepType); + return new PumpEnactResult(injector).success(true).enacted(false); + } + + + public PumpEnactResult getPodStatus() { StatusResponse statusResponse; diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/CommandPlayTestBeep.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/CommandPlayTestBeep.java new file mode 100644 index 0000000000..94ff4996c0 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/queue/command/CommandPlayTestBeep.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.queue.command; + +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType; + +public class CommandPlayTestBeep extends OmnipodCustomCommand { + private BeepConfigType beepType; + + public CommandPlayTestBeep(BeepConfigType beepType) { + super(OmnipodCustomCommandType.PLAY_TEST_BEEP); + this.beepType = beepType; + } + + public BeepConfigType getBeepType() { + return beepType; + } +} 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 e6df62c47b..ab7cb38b39 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 @@ -8,7 +8,9 @@ public enum OmnipodCustomCommandType { RESUME_DELIVERY("RESUME DELIVERY"), DEACTIVATE_POD("DEACTIVATE POD"), HANDLE_TIME_CHANGE("HANDLE TIME CHANGE"), - UPDATE_ALERT_CONFIGURATION("UPDATE ALERT CONFIGURATION"); + UPDATE_ALERT_CONFIGURATION("UPDATE ALERT CONFIGURATION"), + PLAY_TEST_BEEP("EMIT 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 ff8319a557..74aded32fb 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,6 +35,7 @@ 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; @@ -272,6 +273,12 @@ public class PodHistoryActivity extends NoSplashAppCompatActivity { } break; + case PLAY_TEST_BEEP: { + if (historyEntry.getData() != null) { + valueView.setText(historyEntry.getData()); + } + } + break; case GET_POD_STATUS: case GET_POD_INFO: case SET_TIME: diff --git a/omnipod/src/main/res/values/strings.xml b/omnipod/src/main/res/values/strings.xml index 6cfea07b2b..6bc4cc2b11 100644 --- a/omnipod/src/main/res/values/strings.xml +++ b/omnipod/src/main/res/values/strings.xml @@ -255,6 +255,8 @@ Less than a minute ago %1$s and %2$s %1$s ago + Beep config + Play test beep %1$d minute %1$d minutes From 3aace47d576f99c08af07bb3d05a984c6d461b1f Mon Sep 17 00:00:00 2001 From: Artiom Kenibasov Date: Sat, 21 Nov 2020 15:58:39 +0100 Subject: [PATCH 15/27] Add beep in the end of canula insertion --- .../driver/communication/action/InsertCannulaAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java index ff47b1b900..a6fdd139d9 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java @@ -58,7 +58,7 @@ public class InsertCannulaAction implements OmnipodAction { if (podStateManager.getActivationProgress().needsCannulaInsertion()) { communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, - Duration.standardSeconds(1), false, false)); + Duration.standardSeconds(1), false, true)); podStateManager.setActivationProgress(ActivationProgress.INSERTING_CANNULA); } From 8dc75111d24cc6ee13dbd15d02691e6f5759a295 Mon Sep 17 00:00:00 2001 From: Artiom Kenibasov Date: Sat, 21 Nov 2020 17:12:16 +0100 Subject: [PATCH 16/27] Added test beep button and made rileylink stats optional --- .../pump/omnipod/OmnipodPumpPlugin.java | 2 + .../definition/OmnipodStorageKeys.java | 2 + .../omnipod/manager/AapsOmnipodManager.java | 11 ++++ .../omnipod/ui/OmnipodOverviewFragment.kt | 29 ++++++++++ .../src/main/res/drawable/ic_speaker_icon.xml | 14 +++++ .../src/main/res/layout/omnipod_overview.xml | 58 ++++++++++++------- omnipod/src/main/res/values/strings.xml | 6 ++ omnipod/src/main/res/xml/pref_omnipod.xml | 12 ++++ 8 files changed, 112 insertions(+), 22 deletions(-) create mode 100644 omnipod/src/main/res/drawable/ic_speaker_icon.xml diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index c7afc04cf1..3e6b0bef6c 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -309,6 +309,8 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, event.isChanged(getResourceHelper(), R.string.key_omnipod_smb_beeps_enabled) || event.isChanged(getResourceHelper(), R.string.key_omnipod_suspend_delivery_button_enabled) || event.isChanged(getResourceHelper(), R.string.key_omnipod_pulse_log_button_enabled) || + event.isChanged(getResourceHelper(), R.string.key_omnipod_rileylink_stats_button_enabled) || + event.isChanged(getResourceHelper(), R.string.key_omnipod_test_beep_button_enabled) || event.isChanged(getResourceHelper(), R.string.key_omnipod_time_change_event_enabled) || event.isChanged(getResourceHelper(), R.string.key_omnipod_notification_uncertain_tbr_sound_enabled) || event.isChanged(getResourceHelper(), R.string.key_omnipod_notification_uncertain_smb_sound_enabled) || diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodStorageKeys.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodStorageKeys.java index 5a373177fe..b1e6a2c9be 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodStorageKeys.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/definition/OmnipodStorageKeys.java @@ -12,6 +12,7 @@ public class OmnipodStorageKeys { public static final int TBR_BEEPS_ENABLED = R.string.key_omnipod_tbr_beeps_enabled; public static final int SUSPEND_DELIVERY_BUTTON_ENABLED = R.string.key_omnipod_suspend_delivery_button_enabled; public static final int PULSE_LOG_BUTTON_ENABLED = R.string.key_omnipod_pulse_log_button_enabled; + public static final int TEST_BEEP_BUTTON_ENABLED = R.string.key_omnipod_test_beep_button_enabled; public static final int TIME_CHANGE_EVENT_ENABLED = R.string.key_omnipod_time_change_event_enabled; public static final int EXPIRATION_REMINDER_ENABLED = R.string.key_omnipod_expiration_reminder_enabled; public static final int EXPIRATION_REMINDER_HOURS_BEFORE_SHUTDOWN = R.string.key_omnipod_expiration_reminder_hours_before_shutdown; @@ -21,6 +22,7 @@ public class OmnipodStorageKeys { public static final int NOTIFICATION_UNCERTAIN_SMB_SOUND_ENABLED = R.string.key_omnipod_notification_uncertain_smb_sound_enabled; public static final int NOTIFICATION_UNCERTAIN_BOLUS_SOUND_ENABLED = R.string.key_omnipod_notification_uncertain_bolus_sound_enabled; public static final int AUTOMATICALLY_ACKNOWLEDGE_ALERTS_ENABLED = R.string.key_omnipod_automatically_acknowledge_alerts_enabled; + public static final int RILEYLINK_STATS_BUTTON_ENABLED = R.string.key_omnipod_rileylink_stats_button_enabled; } public static class Statistics { 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 9f5333330c..65474891e3 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 @@ -115,6 +115,8 @@ public class AapsOmnipodManager { private boolean notificationUncertainSmbSoundEnabled; private boolean notificationUncertainBolusSoundEnabled; private boolean automaticallyAcknowledgeAlertsEnabled; + private boolean testBeepButtonEnabled; + private boolean rileylinkStatsButtonEnabled; @Inject public AapsOmnipodManager(OmnipodRileyLinkCommunicationManager communicationService, @@ -156,6 +158,8 @@ public class AapsOmnipodManager { tbrBeepsEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.TBR_BEEPS_ENABLED, true); suspendDeliveryButtonEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.SUSPEND_DELIVERY_BUTTON_ENABLED, false); pulseLogButtonEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.PULSE_LOG_BUTTON_ENABLED, false); + testBeepButtonEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.TEST_BEEP_BUTTON_ENABLED, true); + rileylinkStatsButtonEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.RILEYLINK_STATS_BUTTON_ENABLED, false); timeChangeEventEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.TIME_CHANGE_EVENT_ENABLED, true); notificationUncertainTbrSoundEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.NOTIFICATION_UNCERTAIN_TBR_SOUND_ENABLED, true); notificationUncertainSmbSoundEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.NOTIFICATION_UNCERTAIN_SMB_SOUND_ENABLED, true); @@ -629,6 +633,13 @@ public class AapsOmnipodManager { return pulseLogButtonEnabled; } + public boolean isTestBeepButtonEnabled() { + return testBeepButtonEnabled; } + + public boolean isRileylinkStatsButtonEnabled() { + return rileylinkStatsButtonEnabled; + } + public boolean isTimeChangeEventEnabled() { return timeChangeEventEnabled; } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt index 3fd3b27472..bb9123033a 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt @@ -24,6 +24,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin import info.nightscout.androidaps.plugins.pump.omnipod.R import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepConfigType import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager @@ -119,6 +120,12 @@ class OmnipodOverviewFragment : DaggerFragment() { DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_error_failed_to_refresh_status), false)) } + omnipod_overview_button_test_beep.setOnClickListener { + disablePodActionButtons() + commandQueue.customCommand(CommandPlayTestBeep(BeepConfigType.BIP_BIP), + DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_error_failed_to_play_test_beep), false)) + } + omnipod_overview_button_rileylink_stats.setOnClickListener { if (omnipodPumpPlugin.rileyLinkService?.verifyConfiguration() == true) { startActivity(Intent(context, RileyLinkStatusActivity::class.java)) @@ -448,8 +455,11 @@ class OmnipodOverviewFragment : DaggerFragment() { updateSuspendDeliveryButton() updateSetTimeButton() updatePulseLogButton() + updateTestBeepButton() + updateRileylinkStatsButton() } + private fun disablePodActionButtons() { omnipod_overview_button_acknowledge_active_alerts.isEnabled = false omnipod_overview_button_resume_delivery.isEnabled = false @@ -457,6 +467,7 @@ class OmnipodOverviewFragment : DaggerFragment() { omnipod_overview_button_set_time.isEnabled = false omnipod_overview_button_refresh_status.isEnabled = false omnipod_overview_button_pulse_log.isEnabled = false + omnipod_overview_button_test_beep.isEnabled = false } private fun updateRefreshStatusButton() { @@ -510,6 +521,24 @@ class OmnipodOverviewFragment : DaggerFragment() { } } + private fun updateRileylinkStatsButton() { + if (omnipodManager.isRileylinkStatsButtonEnabled) { + omnipod_overview_button_rileylink_stats.visibility = View.VISIBLE + omnipod_overview_button_rileylink_stats.isEnabled = true + } else { + omnipod_overview_button_rileylink_stats.visibility = View.GONE + } + } + + private fun updateTestBeepButton() { + if (omnipodManager.isTestBeepButtonEnabled) { + omnipod_overview_button_test_beep.visibility = View.VISIBLE + omnipod_overview_button_test_beep.isEnabled = podStateManager.isPodActivationCompleted && rileyLinkServiceData.rileyLinkServiceState.isReady && isQueueEmpty() + } else { + omnipod_overview_button_test_beep.visibility = View.GONE + } + } + private fun displayNotConfiguredDialog() { context?.let { UIRunnable(Runnable { diff --git a/omnipod/src/main/res/drawable/ic_speaker_icon.xml b/omnipod/src/main/res/drawable/ic_speaker_icon.xml new file mode 100644 index 0000000000..e642e65ab3 --- /dev/null +++ b/omnipod/src/main/res/drawable/ic_speaker_icon.xml @@ -0,0 +1,14 @@ + + + + diff --git a/omnipod/src/main/res/layout/omnipod_overview.xml b/omnipod/src/main/res/layout/omnipod_overview.xml index ff36031400..2088ac3e4f 100644 --- a/omnipod/src/main/res/layout/omnipod_overview.xml +++ b/omnipod/src/main/res/layout/omnipod_overview.xml @@ -779,28 +779,6 @@ android:paddingRight="0dp" android:text="@string/omnipod_overview_button_acknowledge_active_alerts" /> -