Block until bolus is finished in AapsOmnipodManager and make PodStateCHangedHandler in PodSessionState transient

This commit is contained in:
Bart Sopers 2019-12-03 08:19:36 +01:00
parent 4fcc5bec6f
commit fecfdeb03e
5 changed files with 48 additions and 97 deletions

View file

@ -33,6 +33,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.Canc
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
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.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress;
@ -40,11 +41,13 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedu
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.defs.state.PodStateChangedHandler; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateChangedHandler;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.CommunicationException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.CommunicationException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalDeliveryStatusException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalSetupProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalSetupProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceOutOfSyncException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceOutOfSyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
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;
import io.reactivex.Single;
public class OmnipodManager { public class OmnipodManager {
private static final int ACTION_VERIFICATION_TRIES = 3; private static final int ACTION_VERIFICATION_TRIES = 3;
@ -61,6 +64,9 @@ public class OmnipodManager {
throw new IllegalArgumentException("Communication service cannot be null"); throw new IllegalArgumentException("Communication service cannot be null");
} }
this.communicationService = communicationService; this.communicationService = communicationService;
if(podState != null) {
podState.setStateChangedHandler(podStateChangedHandler);
}
this.podState = podState; this.podState = podState;
this.podStateChangedHandler = podStateChangedHandler; this.podStateChangedHandler = podStateChangedHandler;
} }
@ -144,7 +150,7 @@ public class OmnipodManager {
communicationService.executeAction(new CancelDeliveryAction(podState, DeliveryType.TEMP_BASAL, true)); communicationService.executeAction(new CancelDeliveryAction(podState, DeliveryType.TEMP_BASAL, true));
} }
public synchronized void bolus(Double units, StatusResponseHandler bolusCompletionHandler) { public Single<StatusResponse> bolus(Double units) {
assertReadyForDelivery(); assertReadyForDelivery();
try { try {
@ -173,22 +179,18 @@ public class OmnipodManager {
} }
} }
if (bolusCompletionHandler != null) { return Single.create(emitter -> executeDelayed(() -> {
executeDelayed(() -> {
for (int i = 0; ACTION_VERIFICATION_TRIES > i; i++) {
StatusResponse statusResponse = null;
try { try {
statusResponse = getPodStatus(); StatusResponse statusResponse = getPodStatus();
if (statusResponse.getDeliveryStatus().isBolusing()) { if (statusResponse.getDeliveryStatus().isBolusing()) {
break; emitter.onError(new IllegalDeliveryStatusException(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus()));
} else {
emitter.onSuccess(statusResponse);
} }
} catch (Exception ex) { } catch (Exception ex) {
// Ignore emitter.onError(ex);
}
bolusCompletionHandler.handle(statusResponse);
}
}, calculateBolusDuration(units, OmnipodConst.POD_BOLUS_DELIVERY_RATE));
} }
}, calculateBolusDuration(units, OmnipodConst.POD_BOLUS_DELIVERY_RATE)));
} }
public synchronized void cancelBolus() { public synchronized void cancelBolus() {

View file

@ -50,7 +50,8 @@ public class PairAction implements OmnipodAction<PodSessionState> {
PodSessionState podState = new PodSessionState(timeZone, address, activationDate, confirmPairingResponse.getPiVersion(), PodSessionState podState = new PodSessionState(timeZone, address, activationDate, confirmPairingResponse.getPiVersion(),
confirmPairingResponse.getPmVersion(), confirmPairingResponse.getLot(), confirmPairingResponse.getTid(), confirmPairingResponse.getPmVersion(), confirmPairingResponse.getLot(), confirmPairingResponse.getTid(),
setupState.getPacketNumber(), setupState.getMessageNumber(), podStateChangedHandler); setupState.getPacketNumber(), setupState.getMessageNumber());
podState.setStateChangedHandler(podStateChangedHandler);
podState.setSetupProgress(SetupProgress.POD_CONFIGURED); podState.setSetupProgress(SetupProgress.POD_CONFIGURED);
return podState; return podState;

View file

@ -26,7 +26,7 @@ import info.nightscout.androidaps.utils.SP;
public class PodSessionState extends PodState { public class PodSessionState extends PodState {
private final Map<AlertSlot, AlertType> configuredAlerts; private final Map<AlertSlot, AlertType> configuredAlerts;
private final PodStateChangedHandler stateChangedHandler; private transient PodStateChangedHandler stateChangedHandler;
private DateTime activatedAt; private DateTime activatedAt;
private DateTime expiresAt; private DateTime expiresAt;
private final FirmwareVersion piVersion; private final FirmwareVersion piVersion;
@ -43,8 +43,7 @@ public class PodSessionState extends PodState {
private DeliveryStatus lastDeliveryStatus; private DeliveryStatus lastDeliveryStatus;
public PodSessionState(DateTimeZone timeZone, int address, DateTime activatedAt, FirmwareVersion piVersion, public PodSessionState(DateTimeZone timeZone, int address, DateTime activatedAt, FirmwareVersion piVersion,
FirmwareVersion pmVersion, int lot, int tid, int packetNumber, int messageNumber, FirmwareVersion pmVersion, int lot, int tid, int packetNumber, int messageNumber) {
PodStateChangedHandler stateChangedHandler) {
super(address, messageNumber, packetNumber); super(address, messageNumber, packetNumber);
if (timeZone == null) { if (timeZone == null) {
throw new IllegalArgumentException("Time zone can not be null"); throw new IllegalArgumentException("Time zone can not be null");
@ -61,11 +60,17 @@ public class PodSessionState extends PodState {
this.pmVersion = pmVersion; this.pmVersion = pmVersion;
this.lot = lot; this.lot = lot;
this.tid = tid; this.tid = tid;
this.stateChangedHandler = stateChangedHandler;
this.nonceState = new NonceState(lot, tid); this.nonceState = new NonceState(lot, tid);
store(); store();
} }
public void setStateChangedHandler(PodStateChangedHandler handler) {
if(stateChangedHandler != null) {
throw new IllegalStateException("A PodStateChangedHandler has already been already registered");
}
stateChangedHandler = handler;
}
public AlertType getConfiguredAlertType(AlertSlot alertSlot) { public AlertType getConfiguredAlertType(AlertSlot alertSlot) {
return configuredAlerts.get(alertSlot); return configuredAlerts.get(alertSlot);
} }

View file

@ -45,6 +45,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodExceptio
import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodFaultException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodFaultException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodReturnedErrorResponseException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodReturnedErrorResponseException;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
import io.reactivex.Single;
public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface { public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface {
private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
@ -147,33 +148,32 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
@Override @Override
public PumpEnactResult setBolus(Double amount) { public PumpEnactResult setBolus(Double amount) {
try { try {
delegate.bolus(amount, statusResponse -> { Single<StatusResponse> responseObserver = delegate.bolus(amount);
// TODO set device driver to available here
// BS: We could optionally use the status response from the command completion verification, // At this point, we know that the bolus command has been succesfully sent
// But I don't think we can use that information in any useful way
if (statusResponse == null) { try {
// Failed to retrieve status response after bolus // Wait for the bolus to finish
// Bolus probably finished anyway StatusResponse statusResponse = responseObserver.blockingGet();
} else if (statusResponse.getDeliveryStatus().isBolusing()) {
// This shouldn't happen
} else {
// Bolus successfully completed
}
});
// TODO set device driver busy here
} catch (Exception ex) { } catch (Exception ex) {
if (loggingEnabled()) {
LOG.debug("Ignoring failed status response for bolus completion verification", ex);
}
}
return new PumpEnactResult().success(true).enacted(true);
} catch (Exception ex) {
// Sending the command failed
String comment = handleAndTranslateException(ex); String comment = handleAndTranslateException(ex);
if (OmnipodManager.isCertainFailure(ex)) { if (OmnipodManager.isCertainFailure(ex)) {
return new PumpEnactResult().success(false).enacted(false).comment(comment); return new PumpEnactResult().success(false).enacted(false).comment(comment);
} else { } else {
// TODO notify user about uncertain failure // TODO notify user about uncertain failure
// we don't know if the bolus failed, so for safety reasons, we choose to register the bolus as succesful. // we don't know if the bolus failed, so for safety reasons, we choose to register the bolus as succesful.
return new PumpEnactResult().success(true).enacted(true); // TODO also manually sleep until the bolus should have been finished here (after notifying the user)
return new PumpEnactResult().success(true).enacted(true).comment(comment);
} }
} }
return new PumpEnactResult().success(true).enacted(true);
} }
@Override @Override
@ -306,7 +306,9 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
String comment = null; String comment = null;
switch (res.getResultType()) { switch (res.getResultType()) {
case FAILURE: case FAILURE:
if (loggingEnabled()) {
LOG.error("Setup action failed: illegal setup progress: {}", res.getSetupProgress()); LOG.error("Setup action failed: illegal setup progress: {}", res.getSetupProgress());
}
comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state, res.getSetupProgress()); comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state, res.getSetupProgress());
break; break;
case VERIFICATION_FAILURE: case VERIFICATION_FAILURE:

View file

@ -1,59 +0,0 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
/**
* Created by mike on 20.09.2017.
*/
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS)
public class TDD {
private static Logger log = LoggerFactory.getLogger(L.DATABASE);
@DatabaseField(id = true)
public long date;
@DatabaseField
public double bolus;
@DatabaseField
public double basal;
@DatabaseField
public double total;
public double getTotal(){
return (total > 0d) ? total:(bolus+basal);
}
public TDD() { }
public TDD(long date, double bolus, double basal, double total){
this.date = date;
this.bolus = bolus;
this.basal = basal;
this.total = total;
}
@Override
public String toString() {
return "TDD [" +
"date=" + date +
"date(str)=" + DateTimeUtil.toStringFromTimeInMillis(date) +
", bolus=" + bolus +
", basal=" + basal +
", total=" + total +
']';
}
}