Add verification mechanism for Omnipod bolus

This commit is contained in:
Bart Sopers 2019-11-30 22:51:49 +01:00
parent 8dcadd7a35
commit 27cf316dc7
21 changed files with 170 additions and 103 deletions

View file

@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException;
@ -27,13 +28,14 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType;
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.state.PodState; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodState;
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.IllegalPacketTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalResponseException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceOutOfSyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceResyncException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceResyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NotEnoughDataException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.NotEnoughDataException;
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.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.exception.IllegalPacketTypeException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalResponseException;
/** /**
* Created by andy on 6/29/18. * Created by andy on 6/29/18.
@ -41,7 +43,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalResponse
public class OmnipodCommunicationService extends RileyLinkCommunicationManager { public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
private static final Logger LOG = LoggerFactory.getLogger(OmnipodCommunicationService.class); private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
public OmnipodCommunicationService(RFSpy rfspy) { public OmnipodCommunicationService(RFSpy rfspy) {
super(rfspy); super(rfspy);
@ -73,8 +75,12 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
} }
public <T extends MessageBlock> T sendCommand(Class<T> responseClass, PodState podState, MessageBlock command) { public <T extends MessageBlock> T sendCommand(Class<T> responseClass, PodState podState, MessageBlock command) {
return sendCommand(responseClass, podState, command, true);
}
public <T extends MessageBlock> T sendCommand(Class<T> responseClass, PodState podState, MessageBlock command, boolean automaticallyResyncNone) {
OmnipodMessage message = new OmnipodMessage(podState.getAddress(), Collections.singletonList(command), podState.getMessageNumber()); OmnipodMessage message = new OmnipodMessage(podState.getAddress(), Collections.singletonList(command), podState.getMessageNumber());
return exchangeMessages(responseClass, podState, message); return exchangeMessages(responseClass, podState, message, automaticallyResyncNone);
} }
// Convenience method // Convenience method
@ -83,10 +89,18 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
} }
public <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message) { public <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message) {
return exchangeMessages(responseClass, podState, message, null, null); return exchangeMessages(responseClass, podState, message, true);
}
public <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, boolean automaticallyResyncNonce) {
return exchangeMessages(responseClass, podState, message, null, null, automaticallyResyncNonce);
} }
public synchronized <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { public synchronized <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) {
return exchangeMessages(responseClass, podState, message, addressOverride, ackAddressOverride, true);
}
public synchronized <T extends MessageBlock> T exchangeMessages(Class<T> responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride, boolean automaticallyResyncNonce) {
for (int i = 0; 2 > i; i++) { for (int i = 0; 2 > i; i++) {
if (podState.hasNonceState() && message.isNonceResyncable()) { if (podState.hasNonceState() && message.isNonceResyncable()) {
@ -106,13 +120,16 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
ErrorResponse error = (ErrorResponse) responseMessageBlock; ErrorResponse error = (ErrorResponse) responseMessageBlock;
if (error.getErrorResponseType() == ErrorResponseType.BAD_NONCE) { if (error.getErrorResponseType() == ErrorResponseType.BAD_NONCE) {
podState.resyncNonce(error.getNonceSearchKey(), message.getSentNonce(), message.getSequenceNumber()); podState.resyncNonce(error.getNonceSearchKey(), message.getSentNonce(), message.getSequenceNumber());
message.resyncNonce(podState.getCurrentNonce()); if (automaticallyResyncNonce) {
message.resyncNonce(podState.getCurrentNonce());
} else {
throw new NonceOutOfSyncException();
}
} else { } else {
throw new PodReturnedErrorResponseException((ErrorResponse) responseMessageBlock); throw new PodReturnedErrorResponseException((ErrorResponse) responseMessageBlock);
} }
} else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) { } else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) {
PodInfoFaultEvent faultEvent = ((PodInfoResponse) responseMessageBlock).getPodInfo(); PodInfoFaultEvent faultEvent = ((PodInfoResponse) responseMessageBlock).getPodInfo();
LOG.error("Pod fault: " + faultEvent.getFaultEventCode().name());
podState.setFaultEvent(faultEvent); podState.setFaultEvent(faultEvent);
throw new PodFaultException(faultEvent); throw new PodFaultException(faultEvent);
} else { } else {
@ -189,7 +206,10 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
if (messageBlocks.size() == 0) { if (messageBlocks.size() == 0) {
throw new NotEnoughDataException(receivedMessageData); throw new NotEnoughDataException(receivedMessageData);
} else if (messageBlocks.size() > 1) { } else if (messageBlocks.size() > 1) {
LOG.error("received more than one message block: " + messageBlocks.toString()); // BS: don't expect this to happen
if (isLoggingEnabled()) {
LOG.error("Received more than one message block: {}", messageBlocks.toString());
}
} }
return messageBlocks.get(0); return messageBlocks.get(0);
@ -216,7 +236,13 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
if (RileyLinkBLEError.Timeout.equals(ex.getErrorCode())) { if (RileyLinkBLEError.Timeout.equals(ex.getErrorCode())) {
quiet = true; quiet = true;
} else { } else {
LOG.debug("Ignoring exception in ackUntilQuiet: " + ex.getClass().getSimpleName() + ": " + ex.getErrorCode() + ": " + ex.getMessage()); if (isLoggingEnabled()) {
LOG.debug("Ignoring exception in ackUntilQuiet", ex);
}
}
} catch (OmnipodException ex) {
if (isLoggingEnabled()) {
LOG.debug("Ignoring exception in ackUntilQuiet", ex);
} }
} catch (Exception ex) { } catch (Exception ex) {
throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex); throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
@ -241,7 +267,9 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
try { try {
response = sendAndListen(packet, responseTimeoutMilliseconds, repeatCount, 9, preambleExtensionMilliseconds, OmnipodPacket.class); response = sendAndListen(packet, responseTimeoutMilliseconds, repeatCount, 9, preambleExtensionMilliseconds, OmnipodPacket.class);
} catch (RileyLinkCommunicationException ex) { } catch (RileyLinkCommunicationException ex) {
LOG.debug("Ignoring exception in exchangePackets: " + ex.getClass().getSimpleName() + ": " + ex.getMessage()); if (isLoggingEnabled()) {
LOG.debug("Ignoring exception in exchangePackets", ex);
}
} catch (Exception ex) { } catch (Exception ex) {
throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex); throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
} }
@ -260,4 +288,8 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
} }
throw new CommunicationException(CommunicationException.Type.TIMEOUT); throw new CommunicationException(CommunicationException.Type.TIMEOUT);
} }
private boolean isLoggingEnabled() {
return L.isEnabled(L.PUMPCOMM);
}
} }

View file

@ -3,6 +3,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.TimeZone; import java.util.TimeZone;
@ -10,6 +12,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair; import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.AcknowledgeAlertsAction; 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.BolusAction;
@ -26,20 +29,27 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.Inser
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PairService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PairService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PrimeService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PrimeService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.SetTempBasalService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.SetTempBasalService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.CancelDeliveryCommand;
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.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;
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.CommunicationException;
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.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;
public class OmnipodManager { public class OmnipodManager {
private static final int ACTION_VERIFICATION_TRIES = 3; private static final int ACTION_VERIFICATION_TRIES = 3;
private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
protected final OmnipodCommunicationService communicationService; protected final OmnipodCommunicationService communicationService;
protected PodSessionState podState; protected PodSessionState podState;
@ -128,7 +138,31 @@ public class OmnipodManager {
public void bolus(Double units, StatusResponseHandler bolusCompletionHandler) { public void bolus(Double units, StatusResponseHandler bolusCompletionHandler) {
assertReadyForDelivery(); assertReadyForDelivery();
communicationService.executeAction(new BolusAction(podState, units, true, true)); try {
communicationService.executeAction(new BolusAction(podState, units, true, true));
} catch (Exception ex) {
if (isCertainFailure(ex)) {
throw ex;
} else {
CommandVerificationResult verificationResult = verifyCommand();
switch (verificationResult) {
case CERTAIN_FAILURE:
if (ex instanceof OmnipodException) {
((OmnipodException) ex).setCertainFailure(true);
throw ex;
} else {
OmnipodException newException = new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
newException.setCertainFailure(true);
throw newException;
}
case UNCERTAIN_FAILURE:
throw ex;
case SUCCESS:
// Ignore original exception
break;
}
}
}
if (bolusCompletionHandler != null) { if (bolusCompletionHandler != null) {
executeDelayed(() -> { executeDelayed(() -> {
@ -255,4 +289,46 @@ public class OmnipodManager {
resultHandler.handle(result); resultHandler.handle(result);
} }
} }
// Only works for commands which contain nonce resyncable message blocks
private CommandVerificationResult verifyCommand() {
if (isLoggingEnabled()) {
LOG.warn("Verifying command by using cancel none command to verify nonce");
}
try {
communicationService.sendCommand(StatusResponse.class, podState,
new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.NO_BEEP, DeliveryType.NONE), false);
} catch (NonceOutOfSyncException ex) {
if (isLoggingEnabled()) {
LOG.info("Command resolved to FAILURE (CERTAIN_FAILURE)");
}
return CommandVerificationResult.CERTAIN_FAILURE;
} catch (Exception ex) {
if (isLoggingEnabled()) {
LOG.error("Command unresolved (UNCERTAIN_FAILURE)");
}
return CommandVerificationResult.UNCERTAIN_FAILURE;
}
if (isLoggingEnabled()) {
if (isLoggingEnabled()) {
LOG.info("Command status resolved to SUCCESS");
}
}
return CommandVerificationResult.SUCCESS;
}
public static boolean isCertainFailure(Exception ex) {
return ex instanceof OmnipodException && ((OmnipodException) ex).isCertainFailure();
}
private enum CommandVerificationResult {
SUCCESS,
CERTAIN_FAILURE,
UNCERTAIN_FAILURE
}
private boolean isLoggingEnabled() {
return L.isEnabled(L.PUMP);
}
} }

View file

@ -40,6 +40,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalPodProgr
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalResponseException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalResponseException;
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.MessageDecodingException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.MessageDecodingException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceOutOfSyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceResyncException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.NonceResyncException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.NotEnoughDataException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.NotEnoughDataException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException;
@ -159,7 +160,13 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
}); });
} catch (Exception ex) { } catch (Exception ex) {
String comment = handleAndTranslateException(ex); String comment = handleAndTranslateException(ex);
return new PumpEnactResult().success(false).enacted(false).comment(comment); if(OmnipodManager.isCertainFailure(ex)) {
return new PumpEnactResult().success(false).enacted(false).comment(comment);
} else {
// 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.
return new PumpEnactResult().success(true).enacted(true);
}
} }
return new PumpEnactResult().success(true).enacted(true); return new PumpEnactResult().success(true).enacted(true);
@ -328,6 +335,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
comment = getStringResource(R.string.omnipod_driver_error_invalid_response); comment = getStringResource(R.string.omnipod_driver_error_invalid_response);
} else if (ex instanceof MessageDecodingException) { } else if (ex instanceof MessageDecodingException) {
comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed); comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed);
} else if (ex instanceof NonceOutOfSyncException) {
comment = getStringResource(R.string.omnipod_driver_error_nonce_out_of_sync);
} else if (ex instanceof NonceResyncException) { } else if (ex instanceof NonceResyncException) {
comment = getStringResource(R.string.omnipod_driver_error_nonce_resync_failed); comment = getStringResource(R.string.omnipod_driver_error_nonce_resync_failed);
} else if (ex instanceof NotEnoughDataException) { } else if (ex instanceof NotEnoughDataException) {
@ -347,7 +356,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
} else { } else {
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName()); comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
if (loggingEnabled()) { if (loggingEnabled()) {
LOG.error(String.format("Caught unexpected exception type from OmnipodManager (user-friendly error message: %s)", comment), ex); LOG.error(String.format("Caught unexpected exception type[certainFailure=false] from OmnipodManager (user-friendly error message: %s)", comment), ex);
} }
} }

View file

@ -2,11 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.exception;
public class ActionInitializationException extends OmnipodException { public class ActionInitializationException extends OmnipodException {
public ActionInitializationException(String message) { public ActionInitializationException(String message) {
super(message); super(message, true);
}
@Override
public boolean isCertainFailure() {
return true;
} }
} }

View file

@ -2,11 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.exception;
public class CommandInitializationException extends OmnipodException { public class CommandInitializationException extends OmnipodException {
public CommandInitializationException(String message) { public CommandInitializationException(String message) {
super(message); super(message, true);
}
@Override
public boolean isCertainFailure() {
return true;
} }
} }

View file

@ -4,12 +4,12 @@ public class CommunicationException extends OmnipodException {
private final Type type; private final Type type;
public CommunicationException(Type type) { public CommunicationException(Type type) {
super(type.getDescription()); super(type.getDescription(), false);
this.type = type; this.type = type;
} }
public CommunicationException(Type type, Throwable cause) { public CommunicationException(Type type, Throwable cause) {
super(type.getDescription(), cause); super(type.getDescription() + ": "+ cause, cause, false);
this.type = type; this.type = type;
} }
@ -17,11 +17,6 @@ public class CommunicationException extends OmnipodException {
return type; return type;
} }
@Override
public boolean isCertainFailure() {
return false;
}
public enum Type { public enum Type {
TIMEOUT("Communication timeout"), TIMEOUT("Communication timeout"),
UNEXPECTED_EXCEPTION("Caught an unexpected Exception"); UNEXPECTED_EXCEPTION("Caught an unexpected Exception");

View file

@ -7,7 +7,7 @@ public class CrcMismatchException extends OmnipodException {
private final int actual; private final int actual;
public CrcMismatchException(int expected, int actual) { public CrcMismatchException(int expected, int actual) {
super(String.format(Locale.getDefault(), "CRC mismatch: expected %d, got %d", expected, actual)); super(String.format(Locale.getDefault(), "CRC mismatch: expected %d, got %d", expected, actual), false);
this.expected = expected; this.expected = expected;
this.actual = actual; this.actual = actual;
} }
@ -19,9 +19,4 @@ public class CrcMismatchException extends OmnipodException {
public int getActual() { public int getActual() {
return actual; return actual;
} }
@Override
public boolean isCertainFailure() {
return false;
}
} }

View file

@ -10,7 +10,7 @@ public class IllegalDeliveryStatusException extends OmnipodException {
private final DeliveryStatus actual; private final DeliveryStatus actual;
public IllegalDeliveryStatusException(DeliveryStatus expected, DeliveryStatus actual) { public IllegalDeliveryStatusException(DeliveryStatus expected, DeliveryStatus actual) {
super(String.format(Locale.getDefault(), "Illegal delivery status: %s, expected: %s", actual, expected)); super(String.format(Locale.getDefault(), "Illegal delivery status: %s, expected: %s", actual, expected), true);
this.expected = expected; this.expected = expected;
this.actual = actual; this.actual = actual;
} }
@ -22,9 +22,4 @@ public class IllegalDeliveryStatusException extends OmnipodException {
public DeliveryStatus getActual() { public DeliveryStatus getActual() {
return actual; return actual;
} }
@Override
public boolean isCertainFailure() {
return true;
}
} }

View file

@ -10,7 +10,7 @@ public class IllegalPacketTypeException extends OmnipodException {
public IllegalPacketTypeException(PacketType expected, PacketType actual) { public IllegalPacketTypeException(PacketType expected, PacketType actual) {
super(String.format(Locale.getDefault(), "Illegal packet type: %s, expected %s", super(String.format(Locale.getDefault(), "Illegal packet type: %s, expected %s",
actual, expected)); actual, expected), false);
this.expected = expected; this.expected = expected;
this.actual = actual; this.actual = actual;
} }
@ -23,8 +23,4 @@ public class IllegalPacketTypeException extends OmnipodException {
return actual; return actual;
} }
@Override
public boolean isCertainFailure() {
return false;
}
} }

View file

@ -9,7 +9,7 @@ public class IllegalPodProgressException extends OmnipodException {
private final PodProgressStatus actual; private final PodProgressStatus actual;
public IllegalPodProgressException(PodProgressStatus expected, PodProgressStatus actual) { public IllegalPodProgressException(PodProgressStatus expected, PodProgressStatus actual) {
super(String.format(Locale.getDefault(), "Illegal setup state: %s, expected: %s", actual, expected)); super(String.format(Locale.getDefault(), "Illegal setup state: %s, expected: %s", actual, expected), true);
this.expected = expected; this.expected = expected;
this.actual = actual; this.actual = actual;
} }
@ -21,9 +21,4 @@ public class IllegalPodProgressException extends OmnipodException {
public PodProgressStatus getActual() { public PodProgressStatus getActual() {
return actual; return actual;
} }
@Override
public boolean isCertainFailure() {
return true;
}
} }

View file

@ -10,7 +10,7 @@ public class IllegalResponseException extends OmnipodException {
public IllegalResponseException(String actualClass, MessageBlockType expectedType) { public IllegalResponseException(String actualClass, MessageBlockType expectedType) {
super(String.format(Locale.getDefault(), "Illegal response type: got class of type %s " + super(String.format(Locale.getDefault(), "Illegal response type: got class of type %s " +
"for message block type %s", actualClass, expectedType)); "for message block type %s", actualClass, expectedType), false);
this.actualClass = actualClass; this.actualClass = actualClass;
this.expectedType = expectedType; this.expectedType = expectedType;
} }
@ -22,9 +22,4 @@ public class IllegalResponseException extends OmnipodException {
public MessageBlockType getExpectedType() { public MessageBlockType getExpectedType() {
return expectedType; return expectedType;
} }
@Override
public boolean isCertainFailure() {
return false;
}
} }

View file

@ -9,7 +9,7 @@ public class IllegalSetupProgressException extends OmnipodException {
private final SetupProgress actual; private final SetupProgress actual;
public IllegalSetupProgressException(SetupProgress expected, SetupProgress actual) { public IllegalSetupProgressException(SetupProgress expected, SetupProgress actual) {
super(String.format(Locale.getDefault(), "Illegal setup progress: %s, expected: %s", actual, expected)); super(String.format(Locale.getDefault(), "Illegal setup progress: %s, expected: %s", actual, expected), true);
this.expected = expected; this.expected = expected;
this.actual = actual; this.actual = actual;
} }
@ -22,8 +22,4 @@ public class IllegalSetupProgressException extends OmnipodException {
return actual; return actual;
} }
@Override
public boolean isCertainFailure() {
return true;
}
} }

View file

@ -2,15 +2,10 @@ package info.nightscout.androidaps.plugins.pump.omnipod.exception;
public class MessageDecodingException extends OmnipodException { public class MessageDecodingException extends OmnipodException {
public MessageDecodingException(String message) { public MessageDecodingException(String message) {
super(message); super(message, false);
} }
public MessageDecodingException(String message, Throwable cause) { public MessageDecodingException(String message, Throwable cause) {
super(message, cause); super(message, cause, false);
}
@Override
public boolean isCertainFailure() {
return false;
} }
} }

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.exception;
public class NonceOutOfSyncException extends OmnipodException {
public NonceOutOfSyncException() {
super("Nonce out of sync", true);
}
}

View file

@ -2,11 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.exception;
public class NonceResyncException extends OmnipodException { public class NonceResyncException extends OmnipodException {
public NonceResyncException() { public NonceResyncException() {
super("Nonce resync failed"); super("Nonce resync failed", true);
}
@Override
public boolean isCertainFailure() {
return true;
} }
} }

View file

@ -6,16 +6,11 @@ public class NotEnoughDataException extends OmnipodException {
private final byte[] data; private final byte[] data;
public NotEnoughDataException(byte[] data) { public NotEnoughDataException(byte[] data) {
super("Not enough data: " + ByteUtil.shortHexString(data)); super("Not enough data: " + ByteUtil.shortHexString(data), false);
this.data = data; this.data = data;
} }
public byte[] getData() { public byte[] getData() {
return data; return data;
} }
@Override
public boolean isCertainFailure() {
return false;
}
} }

View file

@ -1,13 +1,23 @@
package info.nightscout.androidaps.plugins.pump.omnipod.exception; package info.nightscout.androidaps.plugins.pump.omnipod.exception;
public abstract class OmnipodException extends RuntimeException { public abstract class OmnipodException extends RuntimeException {
public OmnipodException(String message) { private boolean certainFailure;
public OmnipodException(String message, boolean certainFailure) {
super(message); super(message);
this.certainFailure = certainFailure;
} }
public OmnipodException(String message, Throwable cause) { public OmnipodException(String message, Throwable cause, boolean certainFailure) {
super(message, cause); super(message, cause);
this.certainFailure = certainFailure;
} }
public abstract boolean isCertainFailure(); public boolean isCertainFailure() {
return certainFailure;
}
public void setCertainFailure(boolean certainFailure) {
this.certainFailure = certainFailure;
}
} }

View file

@ -9,16 +9,11 @@ public class PodFaultException extends OmnipodException {
public PodFaultException(PodInfoFaultEvent faultEvent) { public PodFaultException(PodInfoFaultEvent faultEvent) {
super(String.format(Locale.getDefault(), "Pod fault (%d): %s", faultEvent.getFaultEventCode().getValue(), super(String.format(Locale.getDefault(), "Pod fault (%d): %s", faultEvent.getFaultEventCode().getValue(),
faultEvent.getFaultEventCode().toString())); faultEvent.getFaultEventCode().toString()), true);
this.faultEvent = faultEvent; this.faultEvent = faultEvent;
} }
public PodInfoFaultEvent getFaultEvent() { public PodInfoFaultEvent getFaultEvent() {
return faultEvent; return faultEvent;
} }
@Override
public boolean isCertainFailure() {
return true;
}
} }

View file

@ -6,16 +6,11 @@ public class PodReturnedErrorResponseException extends OmnipodException {
private final ErrorResponse errorResponse; private final ErrorResponse errorResponse;
public PodReturnedErrorResponseException(ErrorResponse errorResponse) { public PodReturnedErrorResponseException(ErrorResponse errorResponse) {
super("Pod returned error response: " + errorResponse.getErrorResponseType()); super("Pod returned error response: " + errorResponse.getErrorResponseType(), true);
this.errorResponse = errorResponse; this.errorResponse = errorResponse;
} }
public ErrorResponse getErrorResponse() { public ErrorResponse getErrorResponse() {
return errorResponse; return errorResponse;
} }
@Override
public boolean isCertainFailure() {
return true;
}
} }

View file

@ -123,7 +123,7 @@ public class RileyLinkOmnipodService extends RileyLinkService {
podState = gson.fromJson(storedPodState, PodSessionState.class); podState = gson.fromJson(storedPodState, PodSessionState.class);
OmnipodUtil.setPodSessionState(podState); OmnipodUtil.setPodSessionState(podState);
} catch (Exception ex) { } catch (Exception ex) {
LOG.error("Could not deserialize Pod state: " + ex.getClass().getSimpleName() + ": " + ex.getMessage()); LOG.error("Could not deserialize Pod state", ex);
} }
} }
OmnipodCommunicationService omnipodCommunicationService = new OmnipodCommunicationService(rfspy); OmnipodCommunicationService omnipodCommunicationService = new OmnipodCommunicationService(rfspy);

View file

@ -1651,10 +1651,11 @@
<string name="omnipod_driver_error_communication_failed">Communication failed.</string> <string name="omnipod_driver_error_communication_failed">Communication failed.</string>
<string name="omnipod_driver_error_crc_mismatch">Communication failed: Message integrity verification failed.</string> <string name="omnipod_driver_error_crc_mismatch">Communication failed: Message integrity verification failed.</string>
<string name="omnipod_driver_error_invalid_packet_type">Communication failed: received an invalid packet from the pod.</string> <string name="omnipod_driver_error_invalid_packet_type">Communication failed: received an invalid packet from the pod.</string>
<string name="omnipod_driver_error_invalid_progress_state">Communication failed: rhe pod is in a wrong state. Please retry your command.</string> <string name="omnipod_driver_error_invalid_progress_state">Communication failed: the pod is in a wrong state.</string>
<string name="omnipod_driver_error_invalid_response">Communication failed: received an invalid response from the pod.</string> <string name="omnipod_driver_error_invalid_response">Communication failed: received an invalid response from the pod.</string>
<string name="omnipod_driver_error_message_decoding_failed">Communication failed: failed to decode message from the pod.</string> <string name="omnipod_driver_error_message_decoding_failed">Communication failed: failed to decode message from the pod.</string>
<string name="omnipod_driver_error_nonce_resync_failed">Communication failed: nonce resync failed. Please try your command again.</string> <string name="omnipod_driver_error_nonce_resync_failed">Communication failed: nonce resync failed.</string>
<string name="omnipod_driver_error_nonce_out_of_sync">Communication failed: nonce out of sync.</string>
<string name="omnipod_driver_error_not_enough_data">Communication failed: not enough data received from the pod.</string> <string name="omnipod_driver_error_not_enough_data">Communication failed: not enough data received from the pod.</string>
<string name="omnipod_driver_error_pod_fault">A pod fault (%1$s) has been detected. Please deactivate your pod and start a new one.</string> <string name="omnipod_driver_error_pod_fault">A pod fault (%1$s) has been detected. Please deactivate your pod and start a new one.</string>
<string name="omnipod_driver_error_pod_returned_error_response">Communication failed: the pod returned an error response.</string> <string name="omnipod_driver_error_pod_returned_error_response">Communication failed: the pod returned an error response.</string>