From b3933e510d5c2d1bcd2e69c7ce41c1e71a30dd1d Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sat, 17 Oct 2020 12:50:08 +0200 Subject: [PATCH] Re-introduce SetupProgress in order to be able to correctly handle Activation Time Exceeded errors --- .../pump/omnipod/OmnipodPumpPlugin.java | 10 +- .../action/AssignAddressAction.java | 69 ++-- .../action/InsertCannulaAction.java | 35 +- .../communication/action/PrimeAction.java | 37 +- .../communication/action/SetupPodAction.java | 64 ++-- .../driver/definition/SetupProgress.java | 66 ++++ .../IllegalPodProgressException.java | 2 +- .../IllegalSetupProgressException.java | 24 ++ .../driver/manager/OmnipodManager.java | 361 ++++++------------ .../driver/manager/PodStateManager.java | 27 +- .../omnipod/manager/AapsOmnipodManager.java | 4 +- .../omnipod/ui/OmnipodOverviewFragment.kt | 7 +- .../pump/omnipod/ui/PodManagementActivity.kt | 5 +- .../activation/PodActivationWizardActivity.kt | 4 +- .../PodActivationActionFragmentBase.kt | 3 +- 15 files changed, 384 insertions(+), 334 deletions(-) create mode 100644 omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/SetupProgress.java create mode 100644 omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalSetupProgressException.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 8d2e1bf50e..6ce16cb71f 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 @@ -74,6 +74,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.acti import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged; import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodTbrChanged; @@ -254,6 +255,13 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, // When PodStateManager is created, which causes an IllegalArgumentException for DateTimeZones not being recognized podStateManager.loadPodState(); + // BS @ 2020-10-17 FIXME: for backwards compatibility; remove before release + if (podStateManager.isPodInitialized() && + podStateManager.getSetupProgress() == SetupProgress.NONE && + podStateManager.getPodProgressStatus().isAtLeast(PodProgressStatus.ABOVE_FIFTY_UNITS)) { + podStateManager.setSetupProgress(SetupProgress.COMPLETED); + } + lastConnectionTimeMillis = sp.getLong( RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); @@ -922,7 +930,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } private void initializeAfterRileyLinkConnection() { - if (podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus().isAtLeast(PodProgressStatus.PAIRING_COMPLETED)) { + if (podStateManager.getSetupProgress().isAtLeast(SetupProgress.PAIRING_COMPLETED)) { for (int i = 0; STARTUP_STATUS_REQUEST_TRIES > i; i++) { PumpEnactResult result = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); if (result.success) { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java index dbea17fde2..a16c69163a 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java @@ -5,59 +5,68 @@ import org.joda.time.DateTimeZone; import java.util.Collections; import java.util.Random; +import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.AssignAddressCommand; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.VersionResponse; 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.exception.ActivationTimeExceededException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class AssignAddressAction implements OmnipodAction { +public class AssignAddressAction implements OmnipodAction { private final PodStateManager podStateManager; + private final AAPSLogger aapsLogger; - public AssignAddressAction(PodStateManager podStateManager) { + public AssignAddressAction(PodStateManager podStateManager, AAPSLogger aapsLogger) { if (podStateManager == null) { throw new IllegalArgumentException("podStateManager can not be null"); } + if (aapsLogger == null) { + throw new IllegalArgumentException("Logger can not be null"); + } this.podStateManager = podStateManager; + this.aapsLogger = aapsLogger; } @Override - public VersionResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { if (!podStateManager.hasPodState()) { podStateManager.initState(generateRandomAddress()); } - if (podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.REMINDER_INITIALIZED)) { - throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, podStateManager.getPodProgressStatus()); + + if (podStateManager.getSetupProgress().needsPairing()) { + AssignAddressCommand assignAddress = new AssignAddressCommand(podStateManager.getAddress()); + OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, + Collections.singletonList(assignAddress), podStateManager.getMessageNumber()); + + try { + VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, assignAddressMessage, + OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); + + if (!assignAddressResponse.isAssignAddressVersionResponse()) { + throw new IllegalVersionResponseTypeException("assignAddress", "setupPod"); + } + if (assignAddressResponse.getAddress() != podStateManager.getAddress()) { + throw new IllegalMessageAddressException(podStateManager.getAddress(), assignAddressResponse.getAddress()); + } + + podStateManager.setInitializationParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), // + assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus()); + } catch (IllegalPacketTypeException ex) { + if (ex.getActual() == PacketType.ACK && podStateManager.isPodInitialized()) { + // When we already assigned the address before, it's possible to only get an ACK here + aapsLogger.debug("Received ACK instead of response in AssignAddressAction. Ignoring because we already assigned the address successfully"); + } else { + throw ex; + } + } } - AssignAddressCommand assignAddress = new AssignAddressCommand(podStateManager.getAddress()); - OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, - Collections.singletonList(assignAddress), podStateManager.getMessageNumber()); - - VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, assignAddressMessage, - OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); - - if (!assignAddressResponse.isAssignAddressVersionResponse()) { - throw new IllegalVersionResponseTypeException("assignAddress", "setupPod"); - } - if (assignAddressResponse.getAddress() != podStateManager.getAddress()) { - throw new IllegalMessageAddressException(podStateManager.getAddress(), assignAddressResponse.getAddress()); - } - - podStateManager.setInitializationParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), // - assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus()); - - if (podStateManager.isPodActivationTimeExceeded()) { - throw new ActivationTimeExceededException(); - } - - return assignAddressResponse; + return null; } private static int generateRandomAddress() { 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 7dae20fea9..b1adbc1f68 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 @@ -6,16 +6,15 @@ import java.util.List; import java.util.Optional; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.ExpirationReminderBuilder; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; 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.definition.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalSetupProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class InsertCannulaAction implements OmnipodAction { +public class InsertCannulaAction implements OmnipodAction { private final PodStateManager podStateManager; private final BasalSchedule initialBasalSchedule; @@ -37,31 +36,33 @@ public class InsertCannulaAction implements OmnipodAction { } @Override - public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) { - throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null); + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { + if (podStateManager.getSetupProgress().isBefore(SetupProgress.PRIMING_COMPLETED)) { + throw new IllegalSetupProgressException(SetupProgress.PRIMING_COMPLETED, podStateManager.getSetupProgress()); } - if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.BASAL_INITIALIZED)) { + if (podStateManager.getSetupProgress().needsBasalSchedule()) { podStateManager.setBasalSchedule(initialBasalSchedule); communicationService.executeAction(new SetBasalScheduleAction(podStateManager, initialBasalSchedule, true, podStateManager.getScheduleOffset(), false)); + podStateManager.setSetupProgress(SetupProgress.BASAL_INITIALIZED); } - if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.INSERTING_CANNULA)) { + if (podStateManager.getSetupProgress().needsExpirationReminders()) { communicationService.executeAction(new ConfigureAlertsAction(podStateManager, buildAlertConfigurations())); podStateManager.setExpirationAlertTimeBeforeShutdown(expirationReminderTimeBeforeShutdown); podStateManager.setLowReservoirAlertUnits(lowReservoirAlertUnits); - - return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, - Duration.standardSeconds(1), false, false)); - } else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.INSERTING_CANNULA)) { - // Check status - return communicationService.executeAction(new GetStatusAction(podStateManager)); - } else { - throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus()); + podStateManager.setSetupProgress(SetupProgress.EXPIRATION_REMINDERS_SET); } + + if (podStateManager.getSetupProgress().needsCannulaInsertion()) { + communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, + Duration.standardSeconds(1), false, false)); + podStateManager.setSetupProgress(SetupProgress.INSERTING_CANNULA); + } + + return null; } private List buildAlertConfigurations() { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java index 44c50e1a38..6f748e9962 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java @@ -1,13 +1,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.PrimeService; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalSetupProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class PrimeAction implements OmnipodAction { +public class PrimeAction implements OmnipodAction { private final PrimeService service; private final PodStateManager podStateManager; @@ -24,21 +23,27 @@ public class PrimeAction implements OmnipodAction { } @Override - public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) { - throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null); + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { + if (podStateManager.getSetupProgress().isBefore(SetupProgress.PAIRING_COMPLETED)) { + throw new IllegalSetupProgressException(SetupProgress.PAIRING_COMPLETED, podStateManager.getSetupProgress()); } - if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING)) { + + if (podStateManager.getSetupProgress().needsDisableTab5Sub16And17()) { // FaultConfigCommand sets internal pod variables to effectively disable $6x faults which occur more often with a 0 TBR service.executeDisableTab5Sub16And17FaultConfigCommand(communicationService, podStateManager); - - service.executeFinishSetupReminderAlertCommand(communicationService, podStateManager); - return service.executePrimeBolusCommand(communicationService, podStateManager); - } else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.PRIMING)) { - // Check status - return communicationService.executeAction(new GetStatusAction(podStateManager)); - } else { - throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus()); + podStateManager.setSetupProgress(SetupProgress.TAB_5_SUB_16_AND_17_DISABLED); } + + if (podStateManager.getSetupProgress().needsSetupReminders()) { + service.executeFinishSetupReminderAlertCommand(communicationService, podStateManager); + podStateManager.setSetupProgress(SetupProgress.SETUP_REMINDERS_SET); + } + + if (podStateManager.getSetupProgress().needsPriming()) { + service.executePrimeBolusCommand(communicationService, podStateManager); + podStateManager.setSetupProgress(SetupProgress.PRIMING); + } + + return null; } } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java index dc4c06abe2..498e285b0b 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java @@ -4,54 +4,72 @@ import org.joda.time.DateTime; import java.util.Collections; +import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.SetupPodCommand; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.VersionResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActivationTimeExceededException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class SetupPodAction implements OmnipodAction { +public class SetupPodAction implements OmnipodAction { private final PodStateManager podStateManager; + private final AAPSLogger aapsLogger; - public SetupPodAction(PodStateManager podStateManager) { + public SetupPodAction(PodStateManager podStateManager, AAPSLogger aapsLogger) { if (podStateManager == null) { throw new IllegalArgumentException("Pod state manager can not be null"); } + if (aapsLogger == null) { + throw new IllegalArgumentException("Logger can not be null"); + } this.podStateManager = podStateManager; + this.aapsLogger = aapsLogger; } @Override - public VersionResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { - if (!podStateManager.isPodInitialized() || !podStateManager.getPodProgressStatus().equals(PodProgressStatus.REMINDER_INITIALIZED)) { + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { + if (!podStateManager.isPodInitialized()) { throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null); } - DateTime activationDate = DateTime.now(podStateManager.getTimeZone()); - SetupPodCommand setupPodCommand = new SetupPodCommand(podStateManager.getAddress(), activationDate, - podStateManager.getLot(), podStateManager.getTid()); - OmnipodMessage message = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, - Collections.singletonList(setupPodCommand), podStateManager.getMessageNumber()); - VersionResponse setupPodResponse; - setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, - message, OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); + if (podStateManager.getSetupProgress().needsPairing()) { + DateTime activationDate = DateTime.now(podStateManager.getTimeZone()); - if (!setupPodResponse.isSetupPodVersionResponse()) { - throw new IllegalVersionResponseTypeException("setupPod", "assignAddress"); - } - if (setupPodResponse.getAddress() != podStateManager.getAddress()) { - throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress()); + SetupPodCommand setupPodCommand = new SetupPodCommand(podStateManager.getAddress(), activationDate, + podStateManager.getLot(), podStateManager.getTid()); + OmnipodMessage message = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, + Collections.singletonList(setupPodCommand), podStateManager.getMessageNumber()); + + try { + VersionResponse setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, + message, OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); + + if (!setupPodResponse.isSetupPodVersionResponse()) { + throw new IllegalVersionResponseTypeException("setupPod", "assignAddress"); + } + if (setupPodResponse.getAddress() != podStateManager.getAddress()) { + throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress()); + } + } catch (IllegalPacketTypeException ex) { + if (PacketType.ACK.equals(ex.getActual())) { + // Pod is already configured + aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring"); + } else { + throw ex; + } + } + + podStateManager.setSetupProgress(SetupProgress.PAIRING_COMPLETED); } - if (podStateManager.isPodActivationTimeExceeded()) { - throw new ActivationTimeExceededException(); - } - - return setupPodResponse; + return null; } } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/SetupProgress.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/SetupProgress.java new file mode 100644 index 0000000000..874b9a2d3e --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/SetupProgress.java @@ -0,0 +1,66 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition; + +public enum SetupProgress { + NONE, + PAIRING_COMPLETED, + TAB_5_SUB_16_AND_17_DISABLED, + SETUP_REMINDERS_SET, + PRIMING, + PRIMING_COMPLETED, + BASAL_INITIALIZED, + EXPIRATION_REMINDERS_SET, + INSERTING_CANNULA, + COMPLETED; + + public boolean needsPairing() { + return this == NONE; + } + + public boolean needsDisableTab5Sub16And17() { + return this == PAIRING_COMPLETED; + } + + public boolean needsSetupReminders() { + return this == TAB_5_SUB_16_AND_17_DISABLED; + } + + public boolean needsPriming() { + return this == SETUP_REMINDERS_SET; + } + + public boolean needsPrimingVerification() { + return this == PRIMING; + } + + public boolean needsBasalSchedule() { + return this == PRIMING_COMPLETED; + } + + public boolean needsExpirationReminders() { + return this == BASAL_INITIALIZED; + } + + public boolean needsCannulaInsertion() { + return this == EXPIRATION_REMINDERS_SET; + } + + public boolean needsCannulaInsertionVerification() { + return this == INSERTING_CANNULA; + } + + public boolean isCompleted() { + return this == COMPLETED; + } + + public boolean isBefore(SetupProgress other) { + return ordinal() < other.ordinal(); + } + + public boolean isAtLeast(SetupProgress other) { + return ordinal() >= other.ordinal(); + } + + public boolean isAfter(SetupProgress other) { + return ordinal() > other.ordinal(); + } +} \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java index da319d5d83..18719fa1ce 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java @@ -9,7 +9,7 @@ public class IllegalPodProgressException extends OmnipodException { private final PodProgressStatus actual; public IllegalPodProgressException(PodProgressStatus expected, PodProgressStatus actual) { - super(String.format(Locale.getDefault(), "Illegal setup state: %s, expected: %s", actual, expected), true); + super(String.format(Locale.getDefault(), "Illegal Pod progress: %s, expected: %s", actual, expected), true); this.expected = expected; this.actual = actual; } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalSetupProgressException.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalSetupProgressException.java new file mode 100644 index 0000000000..42744496ea --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalSetupProgressException.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.exception; + +import java.util.Locale; + +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress; + +public class IllegalSetupProgressException extends OmnipodException { + private final SetupProgress expected; + private final SetupProgress actual; + + public IllegalSetupProgressException(SetupProgress expected, SetupProgress actual) { + super(String.format(Locale.getDefault(), "Illegal setup progress: %s, expected: %s", actual, expected), true); + this.expected = expected; + this.actual = actual; + } + + public SetupProgress getExpected() { + return expected; + } + + public SetupProgress getActual() { + return actual; + } +} 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 bd87de7499..1f8593eb67 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 @@ -36,16 +36,15 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepTyp import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActivationTimeExceededException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CommandFailedAfterChangingDeliveryStatusException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalDeliveryStatusException; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalSetupProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.NonceOutOfSyncException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.OmnipodException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.PodFaultException; @@ -89,89 +88,54 @@ public class OmnipodManager { } public synchronized Single pairAndPrime() { - if (podStateManager.isPodActivationTimeExceeded()) { - throw new ActivationTimeExceededException(); - } - if (podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.PRIMING)) { - return Single.just(true); - } - - logStartingCommandExecution("pairAndPrime"); - - try { - // Always send both 0x07 and 0x03 on retries - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) { - try { - communicationService.executeAction( - new AssignAddressAction(podStateManager)); - } catch (IllegalPacketTypeException ex) { - if (ex.getActual() == PacketType.ACK && podStateManager.isPodInitialized()) { - // When we already assigned the address before, it's possible to only get an ACK here - aapsLogger.debug("Received ACK instead of response in AssignAddressAction. Ignoring because we already assigned the address successfully"); - } else { - throw ex; - } - } - - try { - communicationService.executeAction(new SetupPodAction(podStateManager)); - } catch (IllegalPacketTypeException ex) { - if (PacketType.ACK.equals(ex.getActual())) { - // Pod is already configured - aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring"); - } - } - } else { - // Make sure we have an up to date PodProgressStatus - getPodStatus(); - - if (podStateManager.isPodActivationTimeExceeded()) { - throw new ActivationTimeExceededException(); - } + if (podStateManager.isPodInitialized()) { + if (podStateManager.getSetupProgress().isAfter(SetupProgress.PRIMING)) { + return Single.just(true); + } + if (podStateManager.getSetupProgress().needsPrimingVerification()) { + return Single.fromCallable(() -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED, SetupProgress.PRIMING_COMPLETED)); } - - communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager)); - - long delayInMillis = calculateEstimatedBolusDuration(DateTime.now().minus(OmnipodConstants.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION), OmnipodConstants.POD_PRIME_BOLUS_UNITS, OmnipodConstants.POD_PRIMING_DELIVERY_RATE).getMillis(); - - return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) // - .map(o -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED)) // - .subscribeOn(Schedulers.io()); - } finally { - logCommandExecutionFinished("pairAndPrime"); } + + // Always send both 0x07 and 0x03 on retries + if (podStateManager.getSetupProgress().isBefore(SetupProgress.PAIRING_COMPLETED)) { + communicationService.executeAction( + new AssignAddressAction(podStateManager, aapsLogger)); + + communicationService.executeAction(new SetupPodAction(podStateManager, aapsLogger)); + } + + communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager)); + + long delayInMillis = calculateEstimatedBolusDuration(DateTime.now().minus(OmnipodConstants.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION), OmnipodConstants.POD_PRIME_BOLUS_UNITS, OmnipodConstants.POD_PRIMING_DELIVERY_RATE).getMillis(); + + return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) // + .map(o -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED, SetupProgress.PRIMING_COMPLETED)) // + .subscribeOn(Schedulers.io()); } public synchronized Single insertCannula( BasalSchedule basalSchedule, Duration expirationReminderTimeBeforeShutdown, Integer lowReservoirAlertUnits) { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) { - throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, !podStateManager.isPodInitialized() ? null : podStateManager.getPodProgressStatus()); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.PRIMING_COMPLETED)) { + throw new IllegalSetupProgressException(SetupProgress.PRIMING_COMPLETED, podStateManager.getSetupProgress()); } - logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]"); - - try { - // Make sure we have the latest PodProgressStatus - getPodStatus(); - - if (podStateManager.isPodActivationTimeExceeded()) { - throw new ActivationTimeExceededException(); - } - if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.INSERTING_CANNULA)) { + if (podStateManager.isPodInitialized()) { + if (podStateManager.getSetupProgress().isCompleted()) { return Single.just(true); } - - communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits)); - - long delayInMillis = calculateEstimatedBolusDuration(DateTime.now().minus(OmnipodConstants.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION), OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConstants.POD_CANNULA_INSERTION_DELIVERY_RATE).getMillis(); - - return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) // - .map(o -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS)) // - .subscribeOn(Schedulers.io()); - - } finally { - logCommandExecutionFinished("insertCannula"); + if (podStateManager.getSetupProgress().needsCannulaInsertionVerification()) { + return Single.fromCallable(() -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS, SetupProgress.COMPLETED)); + } } + + communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits)); + + long delayInMillis = calculateEstimatedBolusDuration(DateTime.now().minus(OmnipodConstants.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION), OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConstants.POD_CANNULA_INSERTION_DELIVERY_RATE).getMillis(); + + return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) // + .map(o -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS, SetupProgress.COMPLETED)) // + .subscribeOn(Schedulers.io()); } public synchronized StatusResponse getPodStatus() { @@ -179,49 +143,29 @@ public class OmnipodManager { throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, null); } - logStartingCommandExecution("getPodStatus"); + return communicationService.executeAction(new GetStatusAction(podStateManager)); - try { - return communicationService.executeAction(new GetStatusAction(podStateManager)); - } finally { - logCommandExecutionFinished("getPodStatus"); - } } public synchronized PodInfoResponse getPodInfo(PodInfoType podInfoType) { assertReadyForDelivery(); - logStartingCommandExecution("getPodInfo"); - - try { - return communicationService.executeAction(new GetPodInfoAction(podStateManager, podInfoType)); - } finally { - logCommandExecutionFinished("getPodInfo"); - } + return communicationService.executeAction(new GetPodInfoAction(podStateManager, podInfoType)); } public synchronized StatusResponse configureAlerts(List alertConfigurations) { assertReadyForDelivery(); - logStartingCommandExecution("configureAlerts"); - try { - StatusResponse statusResponse = executeAndVerify(() -> communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations))); - ConfigureAlertsAction.updateConfiguredAlerts(podStateManager, alertConfigurations); - return statusResponse; - } finally { - logCommandExecutionFinished("configureAlerts"); - } + + StatusResponse statusResponse = executeAndVerify(() -> communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations))); + ConfigureAlertsAction.updateConfiguredAlerts(podStateManager, alertConfigurations); + return statusResponse; + } public synchronized StatusResponse acknowledgeAlerts() { assertReadyForDelivery(); - logStartingCommandExecution("acknowledgeAlerts"); - - try { - return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podStateManager, podStateManager.getActiveAlerts()))); - } finally { - logCommandExecutionFinished("acknowledgeAlerts"); - } + return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podStateManager, podStateManager.getActiveAlerts()))); } // CAUTION: cancels all delivery @@ -229,41 +173,33 @@ public class OmnipodManager { public synchronized void setBasalSchedule(BasalSchedule schedule, boolean acknowledgementBeep) { assertReadyForDelivery(); - logStartingCommandExecution("setBasalSchedule [basalSchedule=" + schedule + ", acknowledgementBeep=" + acknowledgementBeep + "]"); + boolean wasSuspended = podStateManager.isSuspended(); + if (!wasSuspended) { + suspendDelivery(acknowledgementBeep); + } try { - boolean wasSuspended = podStateManager.isSuspended(); - if (!wasSuspended) { - suspendDelivery(acknowledgementBeep); + executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, schedule, + false, podStateManager.getScheduleOffset(), acknowledgementBeep))); + podStateManager.setBasalSchedule(schedule); + } catch (OmnipodException ex) { + if (ex.isCertainFailure()) { + if (!wasSuspended) { + throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); + } + throw ex; } - try { - executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, schedule, - false, podStateManager.getScheduleOffset(), acknowledgementBeep))); + // verifyDeliveryStatus will throw an exception if verification fails + if (verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { podStateManager.setBasalSchedule(schedule); - } catch (OmnipodException ex) { - if (ex.isCertainFailure()) { - if (!wasSuspended) { - throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); - } - throw ex; - } - - // verifyDeliveryStatus will throw an exception if verification fails - if (verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { - podStateManager.setBasalSchedule(schedule); - } else { - if (!wasSuspended) { - throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); - } - ex.setCertainFailure(true); - throw ex; + } else { + if (!wasSuspended) { + throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); } + ex.setCertainFailure(true); + throw ex; } - - - } finally { - logCommandExecutionFinished("setBasalSchedule"); } } @@ -271,70 +207,64 @@ public class OmnipodManager { public synchronized void setTemporaryBasal(double rate, Duration duration, boolean acknowledgementBeep, boolean completionBeep) { assertReadyForDelivery(); - logStartingCommandExecution("setTemporaryBasal [rate=" + rate + ", duration=" + duration + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]"); - boolean cancelCurrentTbr = podStateManager.isTempBasalRunning(); - try { - if (cancelCurrentTbr) { - try { - cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep); - } catch (OmnipodException ex) { - if (ex.isCertainFailure()) { - throw ex; - } - - try { - if (!verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { - ex.setCertainFailure(true); - throw ex; - } - } catch (DeliveryStatusVerificationFailedException ex2) { - podStateManager.setTempBasalCertain(false); - throw ex2; - } - } - } - + if (cancelCurrentTbr) { try { - 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); + cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep); } catch (OmnipodException ex) { if (ex.isCertainFailure()) { - if (cancelCurrentTbr) { - throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); - } throw ex; } - // verifyDeliveryStatus will throw an exception if verification fails try { - if (verifyDeliveryStatus(DeliveryStatus.TEMP_BASAL_RUNNING, ex)) { - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); - } else { - if (cancelCurrentTbr) { - throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); - } - + if (!verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { ex.setCertainFailure(true); throw ex; } - } catch (CommandFailedAfterChangingDeliveryStatusException ex2) { - // Don't set temp basal in Pod State for this Exception - throw ex2; - } catch (OmnipodException ex2) { - if (!ex2.isCertainFailure()) { - // We're not sure that setting the new TBR failed, so we assume that it succeeded - // If it didn't, PodStateManager.updateFromResponse() will fix the state - // upon receiving the next StatusResponse - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, false); - } + } catch (DeliveryStatusVerificationFailedException ex2) { + podStateManager.setTempBasalCertain(false); throw ex2; } } - } finally { - logCommandExecutionFinished("setTemporaryBasal"); + } + + try { + 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); + } catch (OmnipodException ex) { + if (ex.isCertainFailure()) { + if (cancelCurrentTbr) { + throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); + } + throw ex; + } + + // verifyDeliveryStatus will throw an exception if verification fails + try { + if (verifyDeliveryStatus(DeliveryStatus.TEMP_BASAL_RUNNING, ex)) { + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); + } else { + if (cancelCurrentTbr) { + throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); + } + + ex.setCertainFailure(true); + throw ex; + } + } catch (CommandFailedAfterChangingDeliveryStatusException ex2) { + // Don't set temp basal in Pod State for this Exception + throw ex2; + } catch (OmnipodException ex2) { + if (!ex2.isCertainFailure()) { + // We're not sure that setting the new TBR failed, so we assume that it succeeded + // If it didn't, PodStateManager.updateFromResponse() will fix the state + // upon receiving the next StatusResponse + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, false); + } + throw ex2; + } } } @@ -361,17 +291,11 @@ public class OmnipodManager { private synchronized StatusResponse cancelDelivery(EnumSet deliveryTypes, boolean acknowledgementBeep) { assertReadyForDelivery(); - logStartingCommandExecution("cancelDelivery [deliveryTypes=" + deliveryTypes + ", acknowledgementBeep=" + acknowledgementBeep + "]"); - - try { - 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; - }); - } finally { - logCommandExecutionFinished("cancelDelivery"); - } + 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; + }); } // Returns a SingleSubject that returns when the bolus has finished. @@ -380,8 +304,6 @@ public class OmnipodManager { public synchronized BolusCommandResult bolus(Double units, boolean acknowledgementBeep, boolean completionBeep, BiConsumer progressIndicationConsumer) { assertReadyForDelivery(); - logStartingCommandExecution("bolus [units=" + units + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]"); - bolusCommandExecutionSubject = SingleSubject.create(); CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS; @@ -467,8 +389,6 @@ public class OmnipodManager { }) .subscribe()); - logCommandExecutionFinished("bolus"); - return new BolusCommandResult(commandDeliveryStatus, bolusCompletionSubject); } @@ -480,16 +400,12 @@ public class OmnipodManager { throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podStateManager.getLastDeliveryStatus()); } - logStartingCommandExecution("cancelBolus [acknowledgementBeep=" + acknowledgementBeep + "]"); - try { StatusResponse statusResponse = cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep); discardActiveBolusData(statusResponse.getBolusNotDelivered()); } catch (PodFaultException ex) { discardActiveBolusData(ex.getDetailedStatus().getBolusNotDelivered()); throw ex; - } finally { - logCommandExecutionFinished("cancelBolus"); } } } @@ -507,7 +423,6 @@ public class OmnipodManager { public synchronized void suspendDelivery(boolean acknowledgementBeep) { assertReadyForDelivery(); - logStartingCommandExecution("suspendDelivery"); try { cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeep); @@ -521,8 +436,6 @@ public class OmnipodManager { ex.setCertainFailure(true); throw ex; } - } finally { - logCommandExecutionFinished("suspendDelivery"); } } @@ -531,26 +444,20 @@ public class OmnipodManager { public synchronized void setTime(boolean acknowledgementBeeps) { assertReadyForDelivery(); - logStartingCommandExecution("setTime [acknowledgementBeeps=" + acknowledgementBeeps + "]"); + DateTimeZone oldTimeZone = podStateManager.getTimeZone(); try { - DateTimeZone oldTimeZone = podStateManager.getTimeZone(); + // Joda seems to cache the default time zone, so we use the JVM's + DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault())); + podStateManager.setTimeZone(DateTimeZone.getDefault()); - try { - // Joda seems to cache the default time zone, so we use the JVM's - DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault())); - podStateManager.setTimeZone(DateTimeZone.getDefault()); - - setBasalSchedule(podStateManager.getBasalSchedule(), acknowledgementBeeps); - } catch (OmnipodException ex) { - podStateManager.setTimeZone(oldTimeZone); - throw ex; - } - - podStateManager.updateActivatedAt(); - } finally { - logCommandExecutionFinished("setTime"); + setBasalSchedule(podStateManager.getBasalSchedule(), acknowledgementBeeps); + } catch (OmnipodException ex) { + podStateManager.setTimeZone(oldTimeZone); + throw ex; } + + podStateManager.updateActivatedAt(); } public synchronized void deactivatePod() { @@ -558,8 +465,6 @@ public class OmnipodManager { throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, null); } - logStartingCommandExecution("deactivatePod"); - // Try to get pulse log for diagnostics try { PodInfoResponse podInfoResponse = communicationService.executeAction(new GetPodInfoAction(podStateManager, PodInfoType.RECENT_PULSE_LOG)); @@ -574,8 +479,6 @@ public class OmnipodManager { communicationService.executeAction(new DeactivatePodAction(podStateManager, true)); } catch (PodFaultException ex) { aapsLogger.info(LTag.PUMPCOMM, "Ignoring PodFaultException in deactivatePod", ex); - } finally { - logCommandExecutionFinished("deactivatePod"); } podStateManager.discardState(); @@ -605,7 +508,6 @@ public class OmnipodManager { // Only works for commands with nonce resyncable message blocks private StatusResponse executeAndVerify(Supplier supplier) { - logStartingCommandExecution("verifyCommand"); try { return supplier.get(); } catch (OmnipodException originalException) { @@ -629,8 +531,6 @@ public class OmnipodManager { throw originalException; } } - } finally { - logCommandExecutionFinished("verifyCommand"); } } @@ -645,7 +545,7 @@ public class OmnipodManager { * @return true if the Pod's progress status matches the expected status, otherwise false * @throws PodProgressStatusVerificationFailedException in case reading the Pod status fails */ - private boolean verifyPodProgressStatus(PodProgressStatus expectedPodProgressStatus) { + private boolean verifyPodProgressStatus(PodProgressStatus expectedPodProgressStatus, SetupProgress setupProgress) { Boolean result = null; Throwable lastException = null; @@ -654,6 +554,7 @@ public class OmnipodManager { StatusResponse statusResponse = getPodStatus(); if (statusResponse.getPodProgressStatus().equals(expectedPodProgressStatus)) { + podStateManager.setSetupProgress(setupProgress); return true; } else { result = false; @@ -694,14 +595,6 @@ public class OmnipodManager { throw new DeliveryStatusVerificationFailedException(expectedStatus, verificationCause); } - private void logStartingCommandExecution(String action) { - aapsLogger.debug(LTag.PUMPCOMM, "Starting command execution for action: " + action); - } - - private void logCommandExecutionFinished(String action) { - aapsLogger.debug(LTag.PUMPCOMM, "Command execution finished for action: " + action); - } - private Duration calculateEstimatedBolusDuration(DateTime startTime, double units, double deliveryRateInUnitsPerSecond) { if (!podStateManager.isPodActivationCompleted()) { // No basal or temp basal is active yet 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 91ab82edfe..38dbeccc8a 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 @@ -16,6 +16,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.function.Supplier; import info.nightscout.androidaps.logging.AAPSLogger; @@ -31,6 +32,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.Firmwar import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodCrc; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule; // TODO add nullchecks on some setters @@ -80,7 +82,7 @@ public abstract class PodStateManager { * @return true if we have a Pod state and the Pod activation has been completed. The pod could also be dead at this point */ public final boolean isPodActivationCompleted() { - return isPodInitialized() && podState.getPodProgressStatus().isAtLeast(PodProgressStatus.ABOVE_FIFTY_UNITS) && !isPodActivationTimeExceeded(); + return getSetupProgress().isCompleted(); } /** @@ -335,6 +337,17 @@ public abstract class PodStateManager { return activatedAt == null ? null : activatedAt.withZone(getSafe(() -> podState.getTimeZone())).plus(OmnipodConstants.NOMINAL_POD_LIFE); } + public final SetupProgress getSetupProgress() { + if (hasPodState()) { + return Optional.ofNullable(podState.getSetupProgress()).orElse(SetupProgress.NONE); + } + return SetupProgress.NONE; + } + + public final void setSetupProgress(SetupProgress setupProgress) { + setAndStore(() -> podState.setSetupProgress(setupProgress)); + } + public final PodProgressStatus getPodProgressStatus() { return getSafe(() -> podState.getPodProgressStatus()); } @@ -642,6 +655,7 @@ public abstract class PodStateManager { private Integer totalTicksDelivered; private boolean suspended; private NonceState nonceState; + private SetupProgress setupProgress = SetupProgress.NONE; private PodProgressStatus podProgressStatus; private DeliveryStatus lastDeliveryStatus; private AlertSet activeAlerts; @@ -810,6 +824,14 @@ public abstract class PodStateManager { this.nonceState = nonceState; } + SetupProgress getSetupProgress() { + return setupProgress; + } + + void setSetupProgress(SetupProgress setupProgress) { + this.setupProgress = setupProgress; + } + PodProgressStatus getPodProgressStatus() { return podProgressStatus; } @@ -941,11 +963,12 @@ public abstract class PodStateManager { ", timeZone=" + timeZone + ", activatedAt=" + activatedAt + ", timeActive=" + timeActive + - ", faultEvent=" + faultEventCode + + ", faultEventCode=" + faultEventCode + ", reservoirLevel=" + reservoirLevel + ", totalTicksDelivered=" + totalTicksDelivered + ", suspended=" + suspended + ", nonceState=" + nonceState + + ", setupProgress=" + setupProgress + ", podProgressStatus=" + podProgressStatus + ", lastDeliveryStatus=" + lastDeliveryStatus + ", activeAlerts=" + activeAlerts + 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 f50c09edcf..bbec85241d 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 @@ -62,6 +62,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalM import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalResponseException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalSetupProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.MessageDecodingException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.NonceOutOfSyncException; @@ -770,7 +771,8 @@ public class AapsOmnipodManager { comment = getStringResource(R.string.omnipod_error_crc_mismatch); } else if (ex instanceof IllegalPacketTypeException) { comment = getStringResource(R.string.omnipod_error_invalid_packet_type); - } else if (ex instanceof IllegalPodProgressException || ex instanceof IllegalDeliveryStatusException) { + } else if (ex instanceof IllegalPodProgressException || ex instanceof IllegalSetupProgressException || + ex instanceof IllegalDeliveryStatusException) { comment = getStringResource(R.string.omnipod_error_invalid_progress_state); } else if (ex instanceof IllegalVersionResponseTypeException) { comment = getStringResource(R.string.omnipod_error_invalid_response); 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 168f96180f..3a8326e3fe 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 @@ -25,6 +25,7 @@ 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.OmnipodConstants import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManager @@ -345,9 +346,7 @@ class OmnipodOverviewFragment : DaggerFragment() { if (!podStateManager.isPodInitialized) { resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation) } else { - if (podStateManager.isPodActivationTimeExceeded) { - resourceHelper.gs(R.string.omnipod_pod_status_activation_time_exceeded) - } else if (podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) { + if (podStateManager.setupProgress.isBefore(SetupProgress.PRIMING_COMPLETED)) { resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation) } else { resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_cannula_insertion) @@ -454,7 +453,7 @@ class OmnipodOverviewFragment : DaggerFragment() { } private fun updateRefreshStatusButton() { - omnipod_overview_button_refresh_status.isEnabled = podStateManager.isPodInitialized && podStateManager.podProgressStatus.isAtLeast(PodProgressStatus.PAIRING_COMPLETED) + omnipod_overview_button_refresh_status.isEnabled = podStateManager.isPodInitialized && podStateManager.setupProgress.isAtLeast(SetupProgress.PAIRING_COMPLETED) && rileyLinkServiceData.rileyLinkServiceState.isReady && isQueueEmpty() } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt index 1732c6e204..c47b2b3912 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData import info.nightscout.androidaps.plugins.pump.omnipod.R +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManager @@ -93,8 +94,8 @@ class PodManagementActivity : NoSplashAppCompatActivity() { omnipod_pod_management_waiting_for_rl_layout.visibility = (!rileyLinkServiceData.rileyLinkServiceState.isReady).toVisibility() if (rileyLinkServiceData.rileyLinkServiceState.isReady) { - omnipod_pod_management_button_activate_pod.isEnabled = !podStateManager.isPodActivationCompleted && !podStateManager.isPodActivationTimeExceeded - omnipod_pod_management_button_deactivate_pod.isEnabled = podStateManager.isPodInitialized + omnipod_pod_management_button_activate_pod.isEnabled = !podStateManager.isPodActivationCompleted + omnipod_pod_management_button_deactivate_pod.isEnabled = podStateManager.setupProgress.isAtLeast(SetupProgress.PAIRING_COMPLETED) if (discardButtonEnabled) { omnipod_pod_management_button_discard_pod.isEnabled = true } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt index 183c3c239c..31ad021fef 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.activation import android.os.Bundle import androidx.annotation.IdRes import info.nightscout.androidaps.plugins.pump.omnipod.R -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.common.activity.OmnipodWizardActivityBase import javax.inject.Inject @@ -25,7 +25,7 @@ class PodActivationWizardActivity : OmnipodWizardActivityBase() { setContentView(R.layout.omnipod_pod_activation_wizard_activity) startDestination = savedInstanceState?.getInt(KEY_START_DESTINATION, R.id.fillPodInfoFragment) - ?: if (!podStateManager.isPodInitialized || podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) { + ?: if (!podStateManager.isPodInitialized || podStateManager.setupProgress.isBefore(SetupProgress.PRIMING_COMPLETED)) { R.id.fillPodInfoFragment } else { R.id.attachPodInfoFragment diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt index cb064bebcf..c58888242f 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.activation.fra import android.content.Intent import android.os.Bundle import android.view.View +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.SetupProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.common.fragment.ActionFragmentBase import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.deactivation.PodDeactivationWizardActivity @@ -25,7 +26,7 @@ abstract class PodActivationActionFragmentBase : ActionFragmentBase() { } override fun onActionFailure() { - if (podStateManager.isPodActivationTimeExceeded) { + if (podStateManager.isPodActivationTimeExceeded && podStateManager.setupProgress.isAtLeast(SetupProgress.PAIRING_COMPLETED)) { omnipod_wizard_button_retry.visibility = View.GONE omnipod_wizard_button_deactivate_pod.visibility = View.VISIBLE }