- Rename and refactor PodInfoFaultEvent to PodInfoDetailedStatus

- introduce ActivationTimeExceededException
This commit is contained in:
Bart Sopers 2020-10-17 10:45:28 +02:00
parent e1e9d992e9
commit 2fcae4b19a
21 changed files with 407 additions and 292 deletions

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess
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.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException;
@ -52,6 +53,10 @@ public class AssignAddressAction implements OmnipodAction<VersionResponse> {
podStateManager.setInitializationParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), //
assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus());
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
return assignAddressResponse;
}

View file

@ -9,6 +9,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess
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.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException;
@ -47,6 +48,10 @@ public class SetupPodAction implements OmnipodAction<VersionResponse> {
throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress());
}
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
return setupPodResponse;
}
}

View file

@ -12,9 +12,11 @@ public class ErrorResponse extends MessageBlock {
private static final int MESSAGE_LENGTH = 5;
private final byte errorResponseCode;
private Integer nonceSearchKey; // only valid for BAD_NONCE
private FaultEventCode faultEventCode; // valid for all but BAD_NONCE
private PodProgressStatus podProgressStatus; // valid for all but BAD_NONCE
private final Integer nonceSearchKey; // only valid for BAD_NONCE
private final FaultEventCode faultEventCode; // valid for all but BAD_NONCE
private final PodProgressStatus podProgressStatus; // valid for all but BAD_NONCE
public ErrorResponse(byte[] encodedData) {
if (encodedData.length < MESSAGE_LENGTH) {
@ -24,11 +26,16 @@ public class ErrorResponse extends MessageBlock {
errorResponseCode = encodedData[2];
if (this.errorResponseCode == ERROR_RESPONSE_CODE_BAD_NONCE) {
if (errorResponseCode == ERROR_RESPONSE_CODE_BAD_NONCE) {
nonceSearchKey = ByteUtil.makeUnsignedShort(encodedData[3], encodedData[4]);
faultEventCode = null;
podProgressStatus = null;
} else {
faultEventCode = FaultEventCode.fromByte(encodedData[3]);
podProgressStatus = PodProgressStatus.fromByte(encodedData[4]);
nonceSearchKey = null;
}
}
@ -53,8 +60,7 @@ public class ErrorResponse extends MessageBlock {
return nonceSearchKey;
}
@Override
public String toString() {
@Override public String toString() {
return "ErrorResponse{" +
"errorResponseCode=" + errorResponseCode +
", nonceSearchKey=" + nonceSearchKey +

View file

@ -2,16 +2,19 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mes
import org.joda.time.Duration;
import java.util.Arrays;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ErrorEventInfo;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableResponse {
public class PodInfoDetailedStatus extends PodInfo implements StatusUpdatableResponse {
private static final int MINIMUM_MESSAGE_LENGTH = 21;
private final PodProgressStatus podProgressStatus;
@ -26,16 +29,13 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
private final Duration timeActive;
private final AlertSet unacknowledgedAlerts;
private final boolean faultAccessingTables;
private final boolean loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging;
private final byte loggedFaultEventInternal2bitMainLoopRoutinesVariable;
private final boolean loggedFaultEventImmediateBolusInProgressDuringError;
private final PodProgressStatus loggedFaultEventErrorPodProgressStatus;
private final ErrorEventInfo errorEventInfo;
private final byte receiverLowGain;
private final byte radioRSSI;
private final PodProgressStatus podProgressStatusAtTimeOfFirstLoggedFaultEvent;
private final PodProgressStatus previousPodProgressStatus;
private final byte[] unknownValue;
public PodInfoFaultEvent(byte[] encodedData) {
public PodInfoDetailedStatus(byte[] encodedData) {
super(encodedData);
if (encodedData.length < MINIMUM_MESSAGE_LENGTH) {
@ -70,20 +70,33 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
unacknowledgedAlerts = new AlertSet(encodedData[15]);
faultAccessingTables = encodedData[16] == 0x02;
int loggedFaultEventInfo = ByteUtil.convertUnsignedByteToInt(encodedData[17]);
loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging = (loggedFaultEventInfo & 0x80) == 0x80;
loggedFaultEventInternal2bitMainLoopRoutinesVariable = (byte) ((loggedFaultEventInfo >>> 5) & 0x03);
loggedFaultEventImmediateBolusInProgressDuringError = (loggedFaultEventInfo & 0x10) == 0x10;
loggedFaultEventErrorPodProgressStatus = PodProgressStatus.fromByte((byte) (loggedFaultEventInfo & 0x0f));
byte rawErrorEventInfo = encodedData[17];
if (rawErrorEventInfo == 0x00) {
errorEventInfo = null;
} else {
errorEventInfo = ErrorEventInfo.fromByte(rawErrorEventInfo);
}
receiverLowGain = (byte) (ByteUtil.convertUnsignedByteToInt(encodedData[18]) >>> 6);
radioRSSI = (byte) (encodedData[18] & 0x3f);
podProgressStatusAtTimeOfFirstLoggedFaultEvent = PodProgressStatus.fromByte((byte) (encodedData[19] & 0x0f));
if (ByteUtil.convertUnsignedByteToInt(encodedData[19]) == 0xff) { // this byte is not valid (no fault has occurred)
previousPodProgressStatus = null;
} else {
previousPodProgressStatus = PodProgressStatus.fromByte((byte) (encodedData[19] & 0x0f));
}
unknownValue = ByteUtil.substring(encodedData, 20, 2);
}
@Override
public PodInfoType getType() {
return PodInfoType.FAULT_EVENT;
return PodInfoType.DETAILED_STATUS;
}
public boolean isFaulted() {
return faultEventCode != null;
}
public boolean isActivationTimeExceeded() {
return podProgressStatus == PodProgressStatus.ACTIVATION_TIME_EXCEEDED;
}
@Override public PodProgressStatus getPodProgressStatus() {
@ -134,20 +147,8 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
return faultAccessingTables;
}
public boolean isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging() {
return loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging;
}
public byte getLoggedFaultEventInternal2bitMainLoopRoutinesVariable() {
return loggedFaultEventInternal2bitMainLoopRoutinesVariable;
}
public boolean isLoggedFaultEventImmediateBolusInProgressDuringError() {
return loggedFaultEventImmediateBolusInProgressDuringError;
}
public PodProgressStatus getLoggedFaultEventErrorPodProgressStatus() {
return loggedFaultEventErrorPodProgressStatus;
public ErrorEventInfo getErrorEventInfo() {
return errorEventInfo;
}
public byte getReceiverLowGain() {
@ -158,8 +159,8 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
return radioRSSI;
}
public PodProgressStatus getLoggedFaultEventPodProgressStatus() {
return podProgressStatusAtTimeOfFirstLoggedFaultEvent;
public PodProgressStatus getPreviousPodProgressStatus() {
return previousPodProgressStatus;
}
public byte[] getUnknownValue() {
@ -167,7 +168,7 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
}
@Override public String toString() {
return "PodInfoFaultEvent{" +
return "PodInfoDetailedStatus{" +
"podProgressStatus=" + podProgressStatus +
", deliveryStatus=" + deliveryStatus +
", bolusNotDelivered=" + bolusNotDelivered +
@ -180,14 +181,11 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
", timeActive=" + timeActive +
", unacknowledgedAlerts=" + unacknowledgedAlerts +
", faultAccessingTables=" + faultAccessingTables +
", loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging=" + loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging +
", loggedFaultEventInternal2bitMainLoopRoutinesVariable=" + loggedFaultEventInternal2bitMainLoopRoutinesVariable +
", loggedFaultEventImmediateBolusInProgressDuringError=" + loggedFaultEventImmediateBolusInProgressDuringError +
", loggedFaultEventErrorPodProgressStatus=" + loggedFaultEventErrorPodProgressStatus +
", errorEventInfo=" + errorEventInfo +
", receiverLowGain=" + receiverLowGain +
", radioRSSI=" + radioRSSI +
", podProgressStatusAtTimeOfFirstLoggedFaultEvent=" + podProgressStatusAtTimeOfFirstLoggedFaultEvent +
", unknownValue=" + ByteUtil.shortHexString(unknownValue) +
", previousPodProgressStatus=" + previousPodProgressStatus +
", unknownValue=" + Arrays.toString(unknownValue) +
'}';
}
}

View file

@ -0,0 +1,52 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
public final class ErrorEventInfo {
private final boolean insulinStateTableCorruption;
private final byte internalVariable;
private final boolean immediateBolusInProgress;
private final PodProgressStatus podProgressStatus;
private ErrorEventInfo(boolean insulinStateTableCorruption, byte internalVariable, boolean immediateBolusInProgress, PodProgressStatus podProgressStatus) {
this.insulinStateTableCorruption = insulinStateTableCorruption;
this.internalVariable = internalVariable;
this.immediateBolusInProgress = immediateBolusInProgress;
this.podProgressStatus = podProgressStatus;
}
public static ErrorEventInfo fromByte(byte faultEventInfo) {
int loggedFaultEventInfo = ByteUtil.convertUnsignedByteToInt(faultEventInfo);
boolean insulinStateTableCorruption = (loggedFaultEventInfo & 0x80) == 0x80;
byte internalVariable = (byte) ((loggedFaultEventInfo >>> 5) & 0x03);
boolean immediateBolusInProgress = (loggedFaultEventInfo & 0x10) == 0x10;
PodProgressStatus podProgressStatus = PodProgressStatus.fromByte((byte) (loggedFaultEventInfo & 0x0f));
return new ErrorEventInfo(insulinStateTableCorruption, internalVariable, immediateBolusInProgress, podProgressStatus);
}
public boolean isInsulinStateTableCorruption() {
return insulinStateTableCorruption;
}
public byte getInternalVariable() {
return internalVariable;
}
public boolean isImmediateBolusInProgress() {
return immediateBolusInProgress;
}
public PodProgressStatus getPodProgressStatus() {
return podProgressStatus;
}
@Override public String toString() {
return "ErrorEventInfo{" +
"insulinStateTableCorruption=" + insulinStateTableCorruption +
", internalVariable=" + internalVariable +
", immediateBolusInProgress=" + immediateBolusInProgress +
", podProgressStatus=" + podProgressStatus +
'}';
}
}

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition;
import java.util.Locale;
public enum FaultEventCode {
NO_FAULTS((byte) 0x00),
FAILED_FLASH_ERASE((byte) 0x01),
FAILED_FLASH_STORE((byte) 0x02),
TABLE_CORRUPTION_BASAL_SUBCOMMAND((byte) 0x03),
@ -129,6 +128,9 @@ public enum FaultEventCode {
}
public static FaultEventCode fromByte(byte value) {
if (value == 0x00) { // No faults
return null;
}
for (FaultEventCode type : values()) {
if (type.value == value) {
return type;

View file

@ -3,15 +3,15 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfo;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoActiveAlerts;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDataLog;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultAndInitializationTime;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoOlderPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog;
public enum PodInfoType {
NORMAL((byte) 0x00),
ACTIVE_ALERTS((byte) 0x01),
FAULT_EVENT((byte) 0x02),
DETAILED_STATUS((byte) 0x02),
DATA_LOG((byte) 0x03), // Similar to types $50 & $51. Returns up to the last 60 dwords of data.
FAULT_AND_INITIALIZATION_TIME((byte) 0x05),
RECENT_PULSE_LOG((byte) 0x50), // Starting at $4200
@ -44,8 +44,8 @@ public enum PodInfoType {
throw new UnsupportedOperationException("Cannot decode PodInfoType.NORMAL");
case ACTIVE_ALERTS:
return new PodInfoActiveAlerts(encodedData);
case FAULT_EVENT:
return new PodInfoFaultEvent(encodedData);
case DETAILED_STATUS:
return new PodInfoDetailedStatus(encodedData);
case DATA_LOG:
return new PodInfoDataLog(encodedData, bodyLength);
case FAULT_AND_INITIALIZATION_TIME:

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.exception;
public class ActivationTimeExceededException extends OmnipodException {
public ActivationTimeExceededException() {
super("The Pod's activation time has been exceeded", true);
}
}

View file

@ -1,16 +1,16 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.exception;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus;
public class PodFaultException extends OmnipodException {
private final PodInfoFaultEvent faultEvent;
private final PodInfoDetailedStatus detailedStatus;
public PodFaultException(PodInfoFaultEvent faultEvent) {
super(faultEvent.getFaultEventCode().toString(), true);
this.faultEvent = faultEvent;
public PodFaultException(PodInfoDetailedStatus detailedStatus) {
super(detailedStatus.getFaultEventCode().toString(), true);
this.detailedStatus = detailedStatus;
}
public PodInfoFaultEvent getFaultEvent() {
return faultEvent;
public PodInfoDetailedStatus getDetailedStatus() {
return detailedStatus;
}
}

View file

@ -40,6 +40,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketT
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.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;
@ -88,11 +89,18 @@ public class OmnipodManager {
}
public synchronized Single<Boolean> pairAndPrime() {
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
if (podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.PRIMING)) {
return Single.just(true);
}
logStartingCommandExecution("pairAndPrime");
try {
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) {
// Always send both 0x07 and 0x03 on retries
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) {
try {
communicationService.executeAction(
new AssignAddressAction(podStateManager));
@ -109,28 +117,29 @@ public class OmnipodManager {
communicationService.executeAction(new SetupPodAction(podStateManager));
} catch (IllegalPacketTypeException ex) {
if (PacketType.ACK.equals(ex.getActual())) {
// TODO is this true for the SetupPodCommand?
// Pod is already configured
aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring");
}
}
} else if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.PRIMING)) {
throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, podStateManager.getPodProgressStatus());
}
} else {
// Make sure we have an up to date PodProgressStatus
getPodStatus();
communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager));
} finally {
logCommandExecutionFinished("pairAndPrime");
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
}
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");
}
}
public synchronized Single<Boolean> insertCannula(
@ -139,26 +148,30 @@ public class OmnipodManager {
throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, !podStateManager.isPodInitialized() ? null : podStateManager.getPodProgressStatus());
}
// Make sure we have the latest PodProgressStatus
getPodStatus();
if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.INSERTING_CANNULA)) {
throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, podStateManager.getPodProgressStatus());
}
logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]");
try {
communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits));
} finally {
logCommandExecutionFinished("insertCannula");
// Make sure we have the latest PodProgressStatus
getPodStatus();
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.INSERTING_CANNULA)) {
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");
}
}
public synchronized StatusResponse getPodStatus() {
@ -437,7 +450,7 @@ public class OmnipodManager {
break;
} catch (PodFaultException ex) {
// Subtract units not delivered in case of a Pod failure
bolusNotDelivered = ex.getFaultEvent().getBolusNotDelivered();
bolusNotDelivered = ex.getDetailedStatus().getBolusNotDelivered();
aapsLogger.debug(LTag.PUMPCOMM, "Caught PodFaultException in bolus completion verification", ex);
break;
@ -473,7 +486,7 @@ public class OmnipodManager {
StatusResponse statusResponse = cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep);
discardActiveBolusData(statusResponse.getBolusNotDelivered());
} catch (PodFaultException ex) {
discardActiveBolusData(ex.getFaultEvent().getBolusNotDelivered());
discardActiveBolusData(ex.getDetailedStatus().getBolusNotDelivered());
throw ex;
} finally {
logCommandExecutionFinished("cancelBolus");

View file

@ -21,11 +21,12 @@ import java.util.function.Supplier;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FirmwareVersion;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodCrc;
@ -79,7 +80,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) && podState.getPodProgressStatus() != PodProgressStatus.ACTIVATION_TIME_EXCEEDED;
return isPodInitialized() && podState.getPodProgressStatus().isAtLeast(PodProgressStatus.ABOVE_FIFTY_UNITS) && !isPodActivationTimeExceeded();
}
/**
@ -97,6 +98,13 @@ public abstract class PodStateManager {
return isPodInitialized() && podState.getPodProgressStatus().equals(PodProgressStatus.FAULT_EVENT_OCCURRED);
}
/**
* @return true if the Pod's activation time has been exceeded
*/
public boolean isPodActivationTimeExceeded() {
return isPodInitialized() && getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED;
}
/**
* @return true if we have a Pod state and the Pod is dead, meaning it is either in a fault state or activation time has been exceeded or it is deactivated
*/
@ -232,16 +240,12 @@ public abstract class PodStateManager {
* a fault event, this does NOT necessarily mean that the Pod is not faulted. For a reliable
* indication on whether or not the pod is faulted, see {@link #isPodFaulted() isPodFaulted()}
*/
public final boolean hasFaultEvent() {
return podState != null && podState.getFaultEvent() != null;
public final boolean isFaulted() {
return podState != null && podState.getFaultEventCode() != null;
}
public final PodInfoFaultEvent getFaultEvent() {
return getSafe(() -> podState.getFaultEvent());
}
public final void setFaultEvent(PodInfoFaultEvent faultEvent) {
setAndStore(() -> podState.setFaultEvent(faultEvent));
public final FaultEventCode getFaultEventCode() {
return getSafe(() -> podState.getFaultEventCode());
}
public final AlertType getConfiguredAlertType(AlertSlot alertSlot) {
@ -513,20 +517,20 @@ public abstract class PodStateManager {
/**
* Does not automatically store pod state in order to decrease I/O load
*/
public final void updateFromResponse(StatusUpdatableResponse statusResponse) {
public final void updateFromResponse(StatusUpdatableResponse status) {
setSafe(() -> {
if (podState.getActivatedAt() == null) {
DateTime activatedAtCalculated = DateTime.now().withZone(podState.getTimeZone()).minus(statusResponse.getTimeActive());
DateTime activatedAtCalculated = DateTime.now().withZone(podState.getTimeZone()).minus(status.getTimeActive());
podState.setActivatedAt(activatedAtCalculated);
}
podState.setSuspended(statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED);
podState.setActiveAlerts(statusResponse.getUnacknowledgedAlerts());
podState.setLastDeliveryStatus(statusResponse.getDeliveryStatus());
podState.setReservoirLevel(statusResponse.getReservoirLevel());
podState.setTotalTicksDelivered(statusResponse.getTicksDelivered());
podState.setPodProgressStatus(statusResponse.getPodProgressStatus());
podState.setTimeActive(statusResponse.getTimeActive());
if (statusResponse.getDeliveryStatus().isTbrRunning()) {
podState.setSuspended(status.getDeliveryStatus() == DeliveryStatus.SUSPENDED);
podState.setActiveAlerts(status.getUnacknowledgedAlerts());
podState.setLastDeliveryStatus(status.getDeliveryStatus());
podState.setReservoirLevel(status.getReservoirLevel());
podState.setTotalTicksDelivered(status.getTicksDelivered());
podState.setPodProgressStatus(status.getPodProgressStatus());
podState.setTimeActive(status.getTimeActive());
if (status.getDeliveryStatus().isTbrRunning()) {
if (!isTempBasalCertain() && isTempBasalRunning()) {
podState.setTempBasalCertain(true);
}
@ -535,6 +539,13 @@ public abstract class PodStateManager {
setTempBasal(null, null, null, true, false);
}
podState.setLastUpdatedFromResponse(DateTime.now());
if (status instanceof PodInfoDetailedStatus) {
PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) status;
if (detailedStatus.isFaulted()) {
podState.setFaultEventCode(detailedStatus.getFaultEventCode());
}
}
});
}
@ -626,7 +637,7 @@ public abstract class PodStateManager {
private DateTimeZone timeZone;
private DateTime activatedAt;
private Duration timeActive;
private PodInfoFaultEvent faultEvent;
private FaultEventCode faultEventCode;
private Double reservoirLevel;
private Integer totalTicksDelivered;
private boolean suspended;
@ -751,12 +762,12 @@ public abstract class PodStateManager {
this.timeActive = timeActive;
}
PodInfoFaultEvent getFaultEvent() {
return faultEvent;
FaultEventCode getFaultEventCode() {
return faultEventCode;
}
void setFaultEvent(PodInfoFaultEvent faultEvent) {
this.faultEvent = faultEvent;
void setFaultEventCode(FaultEventCode faultEventCode) {
this.faultEventCode = faultEventCode;
}
Double getReservoirLevel() {
@ -930,7 +941,7 @@ public abstract class PodStateManager {
", timeZone=" + timeZone +
", activatedAt=" + activatedAt +
", timeActive=" + timeActive +
", faultEvent=" + faultEvent +
", faultEvent=" + faultEventCode +
", reservoirLevel=" + reservoirLevel +
", totalTicksDelivered=" + totalTicksDelivered +
", suspended=" + suspended +

View file

@ -50,9 +50,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.Deliver
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
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.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalScheduleEntry;
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.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException;
@ -755,11 +755,9 @@ public class AapsOmnipodManager {
if (ex instanceof OmnipodException) {
aapsLogger.error(LTag.PUMP, String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager", ((OmnipodException) ex).isCertainFailure()), ex);
if (ex instanceof PodFaultException) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode();
if (!(faultEventCode == FaultEventCode.NO_FAULTS && podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED)) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getDetailedStatus().getFaultEventCode();
showPodFaultNotification(faultEventCode);
}
}
} else {
aapsLogger.error(LTag.PUMP, "Caught an unexpected non-OmnipodException from OmnipodManager", ex);
}
@ -791,8 +789,10 @@ public class AapsOmnipodManager {
} else if (ex instanceof NotEnoughDataException) {
comment = getStringResource(R.string.omnipod_error_not_enough_data);
} else if (ex instanceof PodFaultException) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode();
FaultEventCode faultEventCode = ((PodFaultException) ex).getDetailedStatus().getFaultEventCode();
comment = createPodFaultErrorMessage(faultEventCode);
} else if (ex instanceof ActivationTimeExceededException) {
comment = getStringResource(R.string.omnipod_error_pod_fault_activation_time_exceeded);
} else if (ex instanceof PodReturnedErrorResponseException) {
comment = getStringResource(R.string.omnipod_error_pod_returned_error_response);
} else if (ex instanceof RileyLinkUnreachableException) {
@ -813,9 +813,6 @@ public class AapsOmnipodManager {
}
private String createPodFaultErrorMessage(FaultEventCode faultEventCode) {
if (faultEventCode == FaultEventCode.NO_FAULTS && podStateManager.getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED) {
return getStringResource(R.string.omnipod_error_pod_fault_activation_time_exceeded);
}
return getStringResource(R.string.omnipod_error_pod_fault,
ByteUtil.convertUnsignedByteToInt(faultEventCode.getValue()), faultEventCode.name());
}

View file

@ -23,12 +23,13 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.ErrorResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfo;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType;
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.exception.ActivationTimeExceededException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageSequenceNumberException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException;
@ -156,12 +157,21 @@ public class OmnipodRileyLinkCommunicationManager extends RileyLinkCommunication
podStateManager.setLastFailedCommunication(DateTime.now());
throw new PodReturnedErrorResponseException(error);
}
} else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) {
PodInfoFaultEvent faultEvent = (PodInfoFaultEvent) ((PodInfoResponse) responseMessageBlock).getPodInfo();
podStateManager.setFaultEvent(faultEvent);
// Treat as successful communication as the user will get notified and can work with this response
} else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.DETAILED_STATUS) {
PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) ((PodInfoResponse) responseMessageBlock).getPodInfo();
if (detailedStatus.isFaulted()) {
// Treat as successful communication in order to prevent false positive pump unreachable alarms
podStateManager.setLastSuccessfulCommunication(DateTime.now());
throw new PodFaultException(faultEvent);
throw new PodFaultException(detailedStatus);
} else if (detailedStatus.isActivationTimeExceeded()) {
// Treat as successful communication in order to prevent false positive pump unreachable alarms
podStateManager.setLastSuccessfulCommunication(DateTime.now());
throw new ActivationTimeExceededException();
} else {
// Shouldn't happen
podStateManager.setLastFailedCommunication(DateTime.now());
throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType());
}
} else {
podStateManager.setLastFailedCommunication(DateTime.now());
throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType());
@ -174,6 +184,7 @@ public class OmnipodRileyLinkCommunicationManager extends RileyLinkCommunication
} finally {
podStateManager.storePodState();
}
}
private MessageBlock transportMessages(PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) {

View file

@ -272,8 +272,8 @@ class OmnipodOverviewFragment : DaggerFragment() {
})
}
if (podStateManager.hasFaultEvent()) {
val faultEventCode = podStateManager.faultEvent.faultEventCode
if (podStateManager.isFaulted) {
val faultEventCode = podStateManager.faultEventCode
errors.add(resourceHelper.gs(R.string.omnipod_pod_status_pod_fault_description, faultEventCode.value, faultEventCode.name))
}
@ -345,7 +345,7 @@ class OmnipodOverviewFragment : DaggerFragment() {
if (!podStateManager.isPodInitialized) {
resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation)
} else {
if (PodProgressStatus.ACTIVATION_TIME_EXCEEDED == podStateManager.podProgressStatus) {
if (podStateManager.isPodActivationTimeExceeded) {
resourceHelper.gs(R.string.omnipod_pod_status_activation_time_exceeded)
} else if (podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) {
resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation)

View file

@ -93,7 +93,7 @@ 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
omnipod_pod_management_button_activate_pod.isEnabled = !podStateManager.isPodActivationCompleted && !podStateManager.isPodActivationTimeExceeded
omnipod_pod_management_button_deactivate_pod.isEnabled = podStateManager.isPodInitialized
if (discardButtonEnabled) {
omnipod_pod_management_button_discard_pod.isEnabled = true

View file

@ -3,8 +3,6 @@ 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.R
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus
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
@ -27,8 +25,7 @@ abstract class PodActivationActionFragmentBase : ActionFragmentBase() {
}
override fun onActionFailure() {
if (podStateManager.isPodInitialized && podStateManager.podProgressStatus == PodProgressStatus.ACTIVATION_TIME_EXCEEDED) {
omnipod_wizard_action_error.setText(R.string.omnipod_error_pod_fault_activation_time_exceeded)
if (podStateManager.isPodActivationTimeExceeded) {
omnipod_wizard_button_retry.visibility = View.GONE
omnipod_wizard_button_deactivate_pod.visibility = View.VISIBLE
}

View file

@ -65,7 +65,8 @@ public class OmnipodPumpPluginTest {
when(activePluginProvider.getActiveTreatments().getTempBasalFromHistory(anyLong())).thenReturn(null);
when(rileyLinkUtil.getRileyLinkHistory()).thenReturn(new ArrayList<>());
when(injector.androidInjector()).thenReturn(new AndroidInjector<Object>() {
@Override public void inject(Object instance) {}
@Override public void inject(Object instance) {
}
});
Profile profile = mock(Profile.class);

View file

@ -24,7 +24,7 @@ public class GetStatusCommandTest {
@Test
public void testPodInfoTypeFaultEvents() {
GetStatusCommand getStatusCommand = new GetStatusCommand(PodInfoType.FAULT_EVENT);
GetStatusCommand getStatusCommand = new GetStatusCommand(PodInfoType.DETAILED_STATUS);
assertArrayEquals(ByteUtil.fromHexString("0e0102"), getStatusCommand.getRawData());
}

View file

@ -0,0 +1,162 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import org.joda.time.Duration;
import org.junit.Test;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ErrorEventInfo;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
// From https://github.com/ps2/rileylink_ios/blob/omnipod-testing/OmniKitTests/PodInfoTests.swift
public class PodInfoDetailedStatusTest {
@Test
public void testPodInfoFaultEventNoFaultAlerts() {
PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("02080100000a003800000003ff008700000095ff0000"));
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPodProgressStatus());
assertEquals(DeliveryStatus.NORMAL, podInfoDetailedStatus.getDeliveryStatus());
assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001);
assertEquals(0x0a, podInfoDetailedStatus.getPodMessageCounter());
assertNull(podInfoDetailedStatus.getFaultEventCode());
assertTrue(Duration.ZERO.isEqual(podInfoDetailedStatus.getFaultEventTime()));
assertNull(podInfoDetailedStatus.getReservoirLevel());
assertTrue(Duration.standardSeconds(8100).isEqual(podInfoDetailedStatus.getTimeActive()));
assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoDetailedStatus.isFaultAccessingTables());
ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo();
assertNull(errorEventInfo);
assertNull(podInfoDetailedStatus.getPreviousPodProgressStatus());
assertEquals(2, podInfoDetailedStatus.getReceiverLowGain());
assertEquals(21, podInfoDetailedStatus.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventDeliveryErrorDuringPriming() {
PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020f0000000900345c000103ff0001000005ae056029"));
assertEquals(PodProgressStatus.INACTIVE, podInfoDetailedStatus.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus());
assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001);
assertEquals(0x09, podInfoDetailedStatus.getPodMessageCounter());
assertEquals(FaultEventCode.PRIME_OPEN_COUNT_TOO_LOW, podInfoDetailedStatus.getFaultEventCode());
assertTrue(Duration.standardSeconds(60).isEqual(podInfoDetailedStatus.getFaultEventTime()));
assertNull(podInfoDetailedStatus.getReservoirLevel());
assertTrue(Duration.standardSeconds(60).isEqual(podInfoDetailedStatus.getTimeActive()));
assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoDetailedStatus.isFaultAccessingTables());
ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo();
assertFalse(errorEventInfo.isInsulinStateTableCorruption());
assertEquals(0x00, errorEventInfo.getInternalVariable());
assertFalse(errorEventInfo.isImmediateBolusInProgress());
assertEquals(PodProgressStatus.PRIMING_COMPLETED, errorEventInfo.getPodProgressStatus());
assertEquals(PodProgressStatus.PRIMING_COMPLETED, podInfoDetailedStatus.getPreviousPodProgressStatus());
assertEquals(2, podInfoDetailedStatus.getReceiverLowGain());
assertEquals(46, podInfoDetailedStatus.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventErrorShuttingDown() {
PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020d0000000407f28609ff03ff0a0200000823080000"));
assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoDetailedStatus.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus());
assertEquals(2034, podInfoDetailedStatus.getTicksDelivered());
assertEquals(101.7, podInfoDetailedStatus.getInsulinDelivered(), 0.000001);
assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001);
assertEquals(0x04, podInfoDetailedStatus.getPodMessageCounter());
assertEquals(FaultEventCode.BASAL_OVER_INFUSION_PULSE, podInfoDetailedStatus.getFaultEventCode());
assertTrue(Duration.standardMinutes(2559).isEqual(podInfoDetailedStatus.getFaultEventTime()));
assertNull(podInfoDetailedStatus.getReservoirLevel());
assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoDetailedStatus.isFaultAccessingTables());
ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo();
assertFalse(errorEventInfo.isInsulinStateTableCorruption());
assertEquals(0x00, errorEventInfo.getInternalVariable());
assertFalse(errorEventInfo.isImmediateBolusInProgress());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorEventInfo.getPodProgressStatus());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPreviousPodProgressStatus());
assertEquals(0, podInfoDetailedStatus.getReceiverLowGain());
assertEquals(35, podInfoDetailedStatus.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventInsulinNotDelivered() {
PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020f0000010200ec6a026803ff026b000028a7082023"));
assertEquals(PodProgressStatus.INACTIVE, podInfoDetailedStatus.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus());
assertEquals(236, podInfoDetailedStatus.getTicksDelivered());
assertEquals(11.8, podInfoDetailedStatus.getInsulinDelivered(), 0.000001);
assertEquals(0.05, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001);
assertEquals(0x02, podInfoDetailedStatus.getPodMessageCounter());
assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoDetailedStatus.getFaultEventCode());
assertTrue(Duration.standardMinutes(616).isEqual(podInfoDetailedStatus.getFaultEventTime()));
assertNull(podInfoDetailedStatus.getReservoirLevel());
assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoDetailedStatus.isFaultAccessingTables());
ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo();
assertFalse(errorEventInfo.isInsulinStateTableCorruption());
assertEquals(0x01, errorEventInfo.getInternalVariable());
assertFalse(errorEventInfo.isImmediateBolusInProgress());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorEventInfo.getPodProgressStatus());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPreviousPodProgressStatus());
assertEquals(2, podInfoDetailedStatus.getReceiverLowGain());
assertEquals(39, podInfoDetailedStatus.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventMaxBolusNotDelivered() {
PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020f00ffff0200ec6a026803ff026b000028a7082023"));
assertEquals(PodProgressStatus.INACTIVE, podInfoDetailedStatus.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus());
assertEquals(236, podInfoDetailedStatus.getTicksDelivered());
assertEquals(11.8, podInfoDetailedStatus.getInsulinDelivered(), 0.000001);
assertEquals(3276.75, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); // Insane and will not happen, but this verifies that we convert it to an unsigned int
assertEquals(0x02, podInfoDetailedStatus.getPodMessageCounter());
assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoDetailedStatus.getFaultEventCode());
assertTrue(Duration.standardMinutes(616).isEqual(podInfoDetailedStatus.getFaultEventTime()));
assertNull(podInfoDetailedStatus.getReservoirLevel());
assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoDetailedStatus.isFaultAccessingTables());
ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo();
assertFalse(errorEventInfo.isInsulinStateTableCorruption());
assertEquals(0x01, errorEventInfo.getInternalVariable());
assertFalse(errorEventInfo.isImmediateBolusInProgress());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorEventInfo.getPodProgressStatus());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPreviousPodProgressStatus());
assertEquals(2, podInfoDetailedStatus.getReceiverLowGain());
assertEquals(39, podInfoDetailedStatus.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging() {
PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020D00000000000012FFFF03FF00160000879A070000"));
assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoDetailedStatus.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus());
assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001);
assertEquals(0x00, podInfoDetailedStatus.getPodMessageCounter());
assertEquals(FaultEventCode.RESET_DUE_TO_LVD, podInfoDetailedStatus.getFaultEventCode());
assertTrue(Duration.ZERO.isEqual(podInfoDetailedStatus.getFaultEventTime()));
assertNull(podInfoDetailedStatus.getReservoirLevel());
assertTrue(Duration.standardSeconds(1320).isEqual(podInfoDetailedStatus.getTimeActive()));
assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoDetailedStatus.isFaultAccessingTables());
ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo();
assertTrue(errorEventInfo.isInsulinStateTableCorruption());
assertEquals(0x00, errorEventInfo.getInternalVariable());
assertFalse(errorEventInfo.isImmediateBolusInProgress());
assertEquals(PodProgressStatus.INSERTING_CANNULA, errorEventInfo.getPodProgressStatus());
assertEquals(PodProgressStatus.INSERTING_CANNULA, podInfoDetailedStatus.getPreviousPodProgressStatus());
assertEquals(2, podInfoDetailedStatus.getReceiverLowGain());
assertEquals(26, podInfoDetailedStatus.getRadioRSSI());
}
}

View file

@ -1,152 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo;
import org.joda.time.Duration;
import org.junit.Test;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
// From https://github.com/ps2/rileylink_ios/blob/omnipod-testing/OmniKitTests/PodInfoTests.swift
public class PodInfoFaultEventTest {
@Test
public void testPodInfoFaultEventNoFaultAlerts() {
PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("02080100000a003800000003ff008700000095ff0000"));
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatus());
assertEquals(DeliveryStatus.NORMAL, podInfoFaultEvent.getDeliveryStatus());
assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001);
assertEquals(0x0a, podInfoFaultEvent.getPodMessageCounter());
assertEquals(FaultEventCode.NO_FAULTS, podInfoFaultEvent.getFaultEventCode());
assertTrue(Duration.ZERO.isEqual(podInfoFaultEvent.getFaultEventTime()));
assertNull(podInfoFaultEvent.getReservoirLevel());
assertTrue(Duration.standardSeconds(8100).isEqual(podInfoFaultEvent.getTimeActive()));
assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoFaultEvent.isFaultAccessingTables());
assertFalse(podInfoFaultEvent.isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging());
assertEquals(0x00, podInfoFaultEvent.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertFalse(podInfoFaultEvent.isLoggedFaultEventImmediateBolusInProgressDuringError());
assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getLoggedFaultEventPodProgressStatus());
assertEquals(2, podInfoFaultEvent.getReceiverLowGain());
assertEquals(21, podInfoFaultEvent.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventDeliveryErrorDuringPriming() {
PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020f0000000900345c000103ff0001000005ae056029"));
assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus());
assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001);
assertEquals(0x09, podInfoFaultEvent.getPodMessageCounter());
assertEquals(FaultEventCode.PRIME_OPEN_COUNT_TOO_LOW, podInfoFaultEvent.getFaultEventCode());
assertTrue(Duration.standardSeconds(60).isEqual(podInfoFaultEvent.getFaultEventTime()));
assertNull(podInfoFaultEvent.getReservoirLevel());
assertTrue(Duration.standardSeconds(60).isEqual(podInfoFaultEvent.getTimeActive()));
assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoFaultEvent.isFaultAccessingTables());
assertFalse(podInfoFaultEvent.isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging());
assertEquals(0x00, podInfoFaultEvent.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertFalse(podInfoFaultEvent.isLoggedFaultEventImmediateBolusInProgressDuringError());
assertEquals(PodProgressStatus.PRIMING_COMPLETED, podInfoFaultEvent.getLoggedFaultEventPodProgressStatus());
assertEquals(2, podInfoFaultEvent.getReceiverLowGain());
assertEquals(46, podInfoFaultEvent.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventErrorShuttingDown() {
PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020d0000000407f28609ff03ff0a0200000823080000"));
assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoFaultEvent.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus());
assertEquals(2034, podInfoFaultEvent.getTicksDelivered());
assertEquals(101.7, podInfoFaultEvent.getInsulinDelivered(), 0.000001);
assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001);
assertEquals(0x04, podInfoFaultEvent.getPodMessageCounter());
assertEquals(FaultEventCode.BASAL_OVER_INFUSION_PULSE, podInfoFaultEvent.getFaultEventCode());
assertTrue(Duration.standardMinutes(2559).isEqual(podInfoFaultEvent.getFaultEventTime()));
assertNull(podInfoFaultEvent.getReservoirLevel());
assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoFaultEvent.isFaultAccessingTables());
assertFalse(podInfoFaultEvent.isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging());
assertEquals(0x00, podInfoFaultEvent.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getLoggedFaultEventPodProgressStatus());
assertFalse(podInfoFaultEvent.isLoggedFaultEventImmediateBolusInProgressDuringError());
assertEquals(0, podInfoFaultEvent.getReceiverLowGain());
assertEquals(35, podInfoFaultEvent.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventInsulinNotDelivered() {
PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020f0000010200ec6a026803ff026b000028a7082023"));
assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus());
assertEquals(236, podInfoFaultEvent.getTicksDelivered());
assertEquals(11.8, podInfoFaultEvent.getInsulinDelivered(), 0.000001);
assertEquals(0.05, podInfoFaultEvent.getBolusNotDelivered(), 0.000001);
assertEquals(0x02, podInfoFaultEvent.getPodMessageCounter());
assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventCode());
assertTrue(Duration.standardMinutes(616).isEqual(podInfoFaultEvent.getFaultEventTime()));
assertNull(podInfoFaultEvent.getReservoirLevel());
assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoFaultEvent.isFaultAccessingTables());
assertFalse(podInfoFaultEvent.isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging());
assertEquals(0x01, podInfoFaultEvent.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertFalse(podInfoFaultEvent.isLoggedFaultEventImmediateBolusInProgressDuringError());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getLoggedFaultEventPodProgressStatus());
assertEquals(2, podInfoFaultEvent.getReceiverLowGain());
assertEquals(39, podInfoFaultEvent.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventMaxBolusNotDelivered() {
PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020f00ffff0200ec6a026803ff026b000028a7082023"));
assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus());
assertEquals(236, podInfoFaultEvent.getTicksDelivered());
assertEquals(11.8, podInfoFaultEvent.getInsulinDelivered(), 0.000001);
assertEquals(3276.75, podInfoFaultEvent.getBolusNotDelivered(), 0.000001); // Insane and will not happen, but this verifies that we convert it to an unsigned int
assertEquals(0x02, podInfoFaultEvent.getPodMessageCounter());
assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventCode());
assertTrue(Duration.standardMinutes(616).isEqual(podInfoFaultEvent.getFaultEventTime()));
assertNull(podInfoFaultEvent.getReservoirLevel());
assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoFaultEvent.isFaultAccessingTables());
assertFalse(podInfoFaultEvent.isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging());
assertEquals(0x01, podInfoFaultEvent.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertFalse(podInfoFaultEvent.isLoggedFaultEventImmediateBolusInProgressDuringError());
assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getLoggedFaultEventPodProgressStatus());
assertEquals(2, podInfoFaultEvent.getReceiverLowGain());
assertEquals(39, podInfoFaultEvent.getRadioRSSI());
}
@Test
public void testPodInfoFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging() {
PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020D00000000000012FFFF03FF00160000879A070000"));
assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoFaultEvent.getPodProgressStatus());
assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus());
assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001);
assertEquals(0x00, podInfoFaultEvent.getPodMessageCounter());
assertEquals(FaultEventCode.RESET_DUE_TO_LVD, podInfoFaultEvent.getFaultEventCode());
assertTrue(Duration.ZERO.isEqual(podInfoFaultEvent.getFaultEventTime()));
assertNull(podInfoFaultEvent.getReservoirLevel());
assertTrue(Duration.standardSeconds(1320).isEqual(podInfoFaultEvent.getTimeActive()));
assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue());
assertFalse(podInfoFaultEvent.isFaultAccessingTables());
assertTrue(podInfoFaultEvent.isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging());
assertEquals(0x00, podInfoFaultEvent.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertFalse(podInfoFaultEvent.isLoggedFaultEventImmediateBolusInProgressDuringError());
assertEquals(PodProgressStatus.INSERTING_CANNULA, podInfoFaultEvent.getLoggedFaultEventPodProgressStatus());
assertEquals(2, podInfoFaultEvent.getReceiverLowGain());
assertEquals(26, podInfoFaultEvent.getRadioRSSI());
}
}

View file

@ -38,18 +38,18 @@ public class PodInfoResponseTest {
public void testMessageDecoding() {
PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d"));
assertEquals(PodInfoType.FAULT_EVENT, podInfoResponse.getSubType());
assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType());
PodInfoFaultEvent podInfo = (PodInfoFaultEvent) podInfoResponse.getPodInfo();
PodInfoDetailedStatus podInfo = (PodInfoDetailedStatus) podInfoResponse.getPodInfo();
assertFalse(podInfo.isFaultAccessingTables());
assertEquals(0x01, podInfo.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable());
assertEquals(0x01, podInfo.getErrorEventInfo().getInternalVariable());
}
@Test
public void testInvalidPodInfoTypeMessageDecoding() {
PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d"));
assertEquals(PodInfoType.FAULT_EVENT, podInfoResponse.getSubType());
assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType());
thrown.expect(ClassCastException.class);
PodInfoActiveAlerts podInfo = (PodInfoActiveAlerts) podInfoResponse.getPodInfo();