Calculate bolus durations and add bolus completion handler in OmnipodManager

This commit is contained in:
Bart Sopers 2019-11-30 15:16:53 +01:00
parent f84149afa4
commit f2e439a485
5 changed files with 64 additions and 30 deletions

View file

@ -34,11 +34,12 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalSetupProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SP;
public class OmnipodManager { public class OmnipodManager {
private static final int SETUP_ACTION_VERIFICATION_TRIES = 3; private static final int ACTION_VERIFICATION_TRIES = 3;
protected final OmnipodCommunicationService communicationService; protected final OmnipodCommunicationService communicationService;
protected PodSessionState podState; protected PodSessionState podState;
@ -64,7 +65,7 @@ public class OmnipodManager {
executeDelayed(() -> verifySetupAction(statusResponse -> PrimeAction.updatePrimingStatus(podState, statusResponse), // executeDelayed(() -> verifySetupAction(statusResponse -> PrimeAction.updatePrimingStatus(podState, statusResponse), //
SetupProgress.PRIMING_FINISHED, resultHandler), // SetupProgress.PRIMING_FINISHED, resultHandler), //
OmnipodConst.POD_PRIME_DURATION); calculateBolusDuration(OmnipodConst.POD_PRIME_BOLUS_UNITS, OmnipodConst.POD_PRIMING_DELIVERY_RATE));
} else { } else {
// TODO use string resource // TODO use string resource
return new PumpEnactResult().success(false).enacted(false).comment("Illegal setup state: " + podState.getSetupProgress().name()); return new PumpEnactResult().success(false).enacted(false).comment("Illegal setup state: " + podState.getSetupProgress().name());
@ -95,7 +96,7 @@ public class OmnipodManager {
executeDelayed(() -> verifySetupAction(statusResponse -> InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse), // executeDelayed(() -> verifySetupAction(statusResponse -> InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse), //
SetupProgress.COMPLETED, resultHandler), SetupProgress.COMPLETED, resultHandler),
OmnipodConst.POD_CANNULA_INSERTION_DURATION); calculateBolusDuration(OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConst.POD_CANNULA_INSERTION_DELIVERY_RATE));
} catch (Exception ex) { } catch (Exception ex) {
// TODO distinguish between certain and uncertain failures // TODO distinguish between certain and uncertain failures
// TODO user friendly error messages (string resources) // TODO user friendly error messages (string resources)
@ -121,22 +122,12 @@ public class OmnipodManager {
return new PumpEnactResult().success(true).enacted(true); return new PumpEnactResult().success(true).enacted(true);
} }
public PumpEnactResult getPodStatus() { public StatusResponse getPodStatus() {
if (podState == null) { if (podState == null) {
// TODO use string resource throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, null);
return new PumpEnactResult().success(false).enacted(false).comment("Pod should be paired and primed first");
} }
try { return communicationService.executeAction(new GetStatusAction(podState));
// TODO how can we return the status response? Also refer to TODO in interface
StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podState));
} 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 deactivatePod() { public PumpEnactResult deactivatePod() {
@ -181,20 +172,36 @@ public class OmnipodManager {
return new PumpEnactResult().success(true).enacted(true); return new PumpEnactResult().success(true).enacted(true);
} }
public PumpEnactResult bolus(Double units) { public PumpEnactResult bolus(Double units, StatusResponseHandler bolusCompletionHandler) {
if (!isInitialized()) { if (!isInitialized()) {
return createNotInitializedResult(); return createNotInitializedResult();
} }
try { try {
communicationService.executeAction(new BolusAction(podState, units, true, true)); communicationService.executeAction(new BolusAction(podState, units, true, true));
if(bolusCompletionHandler != null) {
executeDelayed(() -> {
for (int i = 0; ACTION_VERIFICATION_TRIES > i; i++) {
StatusResponse statusResponse = null;
try {
statusResponse = getPodStatus();
if (statusResponse.getDeliveryStatus().isBolusing()) {
break;
}
} catch (Exception ex) {
// Ignore
}
bolusCompletionHandler.handle(statusResponse);
}
}, calculateBolusDuration(units, OmnipodConst.POD_BOLUS_DELIVERY_RATE));
}
} catch (Exception ex) { } catch (Exception ex) {
// TODO distinguish between certain and uncertain failures // TODO distinguish between certain and uncertain failures
// TODO user friendly error messages (string resources) // TODO user friendly error messages (string resources)
return new PumpEnactResult().success(false).enacted(false).comment(ex.getMessage()); return new PumpEnactResult().success(false).enacted(false).comment(ex.getMessage());
} }
// TODO calculate bolus duration
return new PumpEnactResult().success(true).enacted(true); return new PumpEnactResult().success(true).enacted(true);
} }
@ -339,6 +346,10 @@ public class OmnipodManager {
return podState == null ? "null" : podState.toString(); return podState == null ? "null" : podState.toString();
} }
private Duration calculateBolusDuration(double units, double deliveryRate) {
return Duration.standardSeconds((long)Math.ceil(units / deliveryRate));
}
private void executeDelayed(Runnable r, Duration timeout) { private void executeDelayed(Runnable r, Duration timeout) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.schedule(r, timeout.getMillis(), TimeUnit.MILLISECONDS); scheduledExecutorService.schedule(r, timeout.getMillis(), TimeUnit.MILLISECONDS);
@ -355,7 +366,7 @@ public class OmnipodManager {
private void verifySetupAction(StatusResponseHandler statusResponseHandler, SetupProgress expectedSetupProgress, SetupActionResultHandler resultHandler) { private void verifySetupAction(StatusResponseHandler statusResponseHandler, SetupProgress expectedSetupProgress, SetupActionResultHandler resultHandler) {
SetupActionResult result = null; SetupActionResult result = null;
for (int i = 0; SETUP_ACTION_VERIFICATION_TRIES > i; i++) { for (int i = 0; ACTION_VERIFICATION_TRIES > i; i++) {
try { try {
StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState)); StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState));
statusResponseHandler.handle(delayedStatusResponse); statusResponseHandler.handle(delayedStatusResponse);
@ -376,11 +387,5 @@ public class OmnipodManager {
if (resultHandler != null) { if (resultHandler != null) {
resultHandler.handle(result); resultHandler.handle(result);
} }
} }
}
@FunctionalInterface
private interface StatusResponseHandler {
void handle(StatusResponse podState);
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
@FunctionalInterface
public interface StatusResponseHandler {
void handle(StatusResponse statusResponse);
}

View file

@ -26,4 +26,8 @@ public enum DeliveryStatus {
public byte getValue() { public byte getValue() {
return value; return value;
} }
public boolean isBolusing() {
return this.equals(BOLUS_IN_PROGRESS) || this.equals(BOLUS_AND_TEMP_BASAL);
}
} }

View file

@ -13,6 +13,7 @@ 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.OmnipodCommunicationService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; 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.SetupActionResult;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType;
@ -66,7 +67,13 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
@Override @Override
public PumpEnactResult getPodStatus() { public PumpEnactResult getPodStatus() {
return delegate.getPodStatus(); try {
StatusResponse statusResponse = delegate.getPodStatus();
return new PumpEnactResult().success(true).enacted(false);
} catch(Exception ex) {
// TODO return string resource
return new PumpEnactResult().success(false).enacted(false).comment(ex.getMessage());
}
} }
@Override @Override
@ -104,7 +111,16 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
@Override @Override
public PumpEnactResult setBolus(Double amount) { public PumpEnactResult setBolus(Double amount) {
return delegate.bolus(amount); return delegate.bolus(amount, statusResponse -> {
if(statusResponse == null) {
// Failed to retrieve status response after bolus
// Bolus probably finished anyway
} else if(statusResponse.getDeliveryStatus().isBolusing()) {
// This shouldn't happen
} else {
// Bolus successfully completed
}
});
} }
@Override @Override

View file

@ -26,6 +26,9 @@ public class OmnipodConst {
} }
public static final double POD_PULSE_SIZE = 0.05; public static final double POD_PULSE_SIZE = 0.05;
public static final double POD_BOLUS_DELIVERY_RATE = 0.025; // units per second
public static final double POD_PRIMING_DELIVERY_RATE = 0.05; // units per second
public static final double POD_CANNULA_INSERTION_DELIVERY_RATE = 0.05; // units per second
public static final double MAX_RESERVOIR_READING = 50.0; public static final double MAX_RESERVOIR_READING = 50.0;
public static final double MAX_BOLUS = 30.0; public static final double MAX_BOLUS = 30.0;
public static final double MAX_BASAL_RATE = 30.0; public static final double MAX_BASAL_RATE = 30.0;
@ -39,6 +42,4 @@ public class OmnipodConst {
public static final double POD_PRIME_BOLUS_UNITS = 2.6; public static final double POD_PRIME_BOLUS_UNITS = 2.6;
public static final double POD_CANNULA_INSERTION_BOLUS_UNITS = 0.5; public static final double POD_CANNULA_INSERTION_BOLUS_UNITS = 0.5;
public static final Duration POD_PRIME_DURATION = Duration.standardSeconds(55);
public static final Duration POD_CANNULA_INSERTION_DURATION = Duration.standardSeconds(10);
} }