diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java index 2ed1f20606..a64b23932e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm; -import android.os.SystemClock; - import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Duration; @@ -15,7 +13,6 @@ import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.AcknowledgeAlertsAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.BolusAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.CancelDeliveryAction; @@ -23,7 +20,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.DeactivatePod import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.GetPodInfoAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.GetStatusAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.InsertCannulaAction; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.PairAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.PrimeAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetBasalScheduleAction; @@ -43,6 +39,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; import info.nightscout.androidaps.utils.SP; public class OmnipodManager { + private static final int SETUP_ACTION_VERIFICATION_TRIES = 3; + protected final OmnipodCommunicationService communicationService; protected PodSessionState podState; @@ -54,7 +52,37 @@ public class OmnipodManager { this.podState = podState; } - public PumpEnactResult insertCannula(Profile profile) { + // Returns a PumpEnactResult which describes whether or not all commands have been sent successfully + // After priming should have finished (55 seconds), the pod state is verified. + // The result of that verification is passed to the SetupActionResultHandler + public PumpEnactResult pairAndPrime(SetupActionResultHandler resultHandler) { + try { + if (podState == null) { + podState = communicationService.executeAction(new PairAction(new PairService())); + } + if (podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { + communicationService.executeAction(new PrimeAction(new PrimeService(), podState)); + + executeDelayed(() -> verifySetupAction(statusResponse -> PrimeAction.updatePrimingStatus(podState, statusResponse), // + SetupProgress.PRIMING_FINISHED, resultHandler), // + OmnipodConst.POD_PRIME_DURATION); + } else { + // TODO use string resource + return new PumpEnactResult().success(false).enacted(false).comment("Illegal setup state: " + podState.getSetupProgress().name()); + } + } catch (Exception ex) { + // TODO distinguish between certain and uncertain failures + // TODO user friendly error messages (string resources) + return new PumpEnactResult().success(false).enacted(false).comment(ex.getMessage()); + } + + return new PumpEnactResult().success(true).enacted(true); + } + + // Returns a PumpEnactResult which describes whether or not all commands have been sent successfully + // After inserting the cannula should have finished (10 seconds), the pod state is verified. + // The result of that verification is passed to the SetupActionResultHandler + public PumpEnactResult insertCannula(Profile profile, SetupActionResultHandler resultHandler) { if (podState == null || podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { // TODO use string resource return new PumpEnactResult().success(false).enacted(false).comment("Pod should be paired and primed first"); @@ -67,39 +95,9 @@ public class OmnipodManager { communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podState, BasalScheduleMapper.mapProfileToBasalSchedule(profile))); - executeDelayed(() -> { - // TODO improve: repeat get status when it fails and handle unexpected statuses - // TODO give user feedback when priming finished (or somehow failed) - StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState)); - InsertCannulaAction.updateCannulaInsertionStatus(podState, delayedStatusResponse); - }, OmnipodConst.POD_CANNULA_INSERTION_DURATION); - } catch (Exception ex) { - // TODO distinguish between certain and uncertain failures - // TODO user friendly error messages (string resources) - return new PumpEnactResult().success(false).enacted(false).comment(ex.getMessage()); - } - - return new PumpEnactResult().success(true).enacted(true); - } - - public PumpEnactResult pairAndPrime() { - try { - if (podState == null) { - podState = communicationService.executeAction(new PairAction(new PairService())); - } - if (podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { - communicationService.executeAction(new PrimeAction(new PrimeService(), podState)); - - executeDelayed(() -> { - // TODO improve: repeat get status when it fails and handle unexpected statuses - // TODO give user feedback when priming finished (or somehow failed) - StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState)); - PrimeAction.updatePrimingStatus(podState, delayedStatusResponse); - }, OmnipodConst.POD_PRIME_DURATION); - } else { - // TODO use string resource - return new PumpEnactResult().success(false).enacted(false).comment("Illegal setup state: " + podState.getSetupProgress().name()); - } + executeDelayed(() -> verifySetupAction(statusResponse -> InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse), // + SetupProgress.COMPLETED, resultHandler), + OmnipodConst.POD_CANNULA_INSERTION_DURATION); } catch (Exception ex) { // TODO distinguish between certain and uncertain failures // TODO user friendly error messages (string resources) @@ -357,4 +355,35 @@ public class OmnipodManager { public PodSessionState getPodState() { return this.podState; } + + private void verifySetupAction(StatusResponseHandler statusResponseHandler, SetupProgress expectedSetupProgress, SetupActionResultHandler resultHandler) { + SetupActionResult result = null; + for (int i = 0; SETUP_ACTION_VERIFICATION_TRIES > i; i++) { + try { + StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState)); + statusResponseHandler.handle(delayedStatusResponse); + + if (podState.getSetupProgress().equals(expectedSetupProgress)) { + result = new SetupActionResult(SetupActionResult.ResultType.SUCCESS); + break; + } else { + result = new SetupActionResult(SetupActionResult.ResultType.FAILURE) // + .setupProgress(podState.getSetupProgress()); + break; + } + } catch (Exception ex) { + result = new SetupActionResult(SetupActionResult.ResultType.VERIFICATION_FAILURE) // + .exception(ex); + } + } + if (resultHandler != null) { + resultHandler.handle(result); + } + + } + + @FunctionalInterface + private interface StatusResponseHandler { + void handle(StatusResponse podState); + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/SetupActionResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/SetupActionResult.java new file mode 100644 index 0000000000..b4c881bfcb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/SetupActionResult.java @@ -0,0 +1,61 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.comm; + +import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; + +public class SetupActionResult { + private final ResultType resultType; + private String message; + private Exception exception; + private SetupProgress setupProgress; + + public SetupActionResult(ResultType resultType) { + this.resultType = resultType; + } + + public SetupActionResult message(String message) { + this.message = message; + return this; + } + + public SetupActionResult exception(Exception ex) { + exception = ex; + return this; + } + + public SetupActionResult setupProgress(SetupProgress setupProgress) { + this.setupProgress = setupProgress; + return this; + } + + public ResultType getResultType() { + return resultType; + } + + public String getMessage() { + return message; + } + + public Exception getException() { + return exception; + } + + public SetupProgress getSetupProgress() { + return setupProgress; + } + + public enum ResultType { + SUCCESS(true), + VERIFICATION_FAILURE(false), + FAILURE(false); + + private final boolean success; + + ResultType(boolean success) { + this.success = success; + } + + public boolean isSuccess() { + return success; + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/SetupActionResultHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/SetupActionResultHandler.java new file mode 100644 index 0000000000..660747a519 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/SetupActionResultHandler.java @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.comm; + +@FunctionalInterface +public interface SetupActionResultHandler { + void handle(SetupActionResult result); +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java index 300e0c287c..9eb03e3f3c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java @@ -15,7 +15,7 @@ public enum PodProgressStatus { TWO_NOT_USED_BUT_IN_33((byte) 0x0b), THREE_NOT_USED_BUT_IN_33((byte) 0x0c), ERROR_EVENT_LOGGED_SHUTTING_DOWN((byte) 0x0d), - DELAYED_PRIME((byte) 0x0e), + a((byte) 0x0e), INACTIVE((byte) 0x0f); private byte value; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 7e73391228..35dd152157 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm; +import org.jetbrains.annotations.Nullable; import org.joda.time.DateTime; import info.nightscout.androidaps.data.Profile; @@ -8,6 +9,7 @@ import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; @@ -36,20 +38,23 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface instance = this; } - @Override public PumpEnactResult initPod(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, Profile profile) { if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) { - PumpEnactResult result = delegate.pairAndPrime(); - podInitReceiver.returnInitTaskStatus(podInitActionType, result.success, (result.success ? null : result.comment)); + PumpEnactResult result = delegate.pairAndPrime(res -> // + podInitReceiver.returnInitTaskStatus(podInitActionType, res.getResultType().isSuccess(), createCommentForSetupActionResult(res))); + if(!result.success) { + podInitReceiver.returnInitTaskStatus(podInitActionType, false, result.comment); + } return result; } else if (PodInitActionType.FillCannulaSetBasalProfileWizardStep.equals(podInitActionType)) { - // FIXME we need a basal profile here - PumpEnactResult result = delegate.insertCannula(profile); - podInitReceiver.returnInitTaskStatus(podInitActionType, result.success, (result.success ? null : result.comment)); - if (result.success) { + PumpEnactResult result = delegate.insertCannula(profile, res -> { + podInitReceiver.returnInitTaskStatus(podInitActionType, res.getResultType().isSuccess(), createCommentForSetupActionResult(res)); OmnipodUtil.setPodSessionState(delegate.getPodState()); RxBus.INSTANCE.send(new EventOmnipodPumpValuesChanged()); + }); + if (!result.success) { + podInitReceiver.returnInitTaskStatus(podInitActionType, false, result.comment); } return result; } @@ -75,8 +80,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return result; } - - @Override public PumpEnactResult setBasalProfile(Profile basalProfile) { return delegate.setBasalProfile(basalProfile); @@ -170,4 +173,18 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface } + + @Nullable + private String createCommentForSetupActionResult(SetupActionResult res) { + String comment = null; + switch(res.getResultType()) { + case FAILURE: + comment = "Unexpected setup progress: "+ res.getSetupProgress(); + break; + case VERIFICATION_FAILURE: + comment = "Verification failed: "+ res.getException().getClass().getSimpleName() +": "+ res.getException().getMessage(); + break; + } + return comment; + } }