- 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.communication.message.response.VersionResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; 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.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.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; 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(), // podStateManager.setInitializationParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), //
assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus()); assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus());
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
return assignAddressResponse; 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.communication.message.response.VersionResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; 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.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.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; 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()); throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress());
} }
if (podStateManager.isPodActivationTimeExceeded()) {
throw new ActivationTimeExceededException();
}
return setupPodResponse; return setupPodResponse;
} }
} }

View file

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

View file

@ -2,16 +2,19 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mes
import org.joda.time.Duration; import org.joda.time.Duration;
import java.util.Arrays;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; 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.communication.message.response.StatusUpdatableResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet; 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.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.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; 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.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; 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 static final int MINIMUM_MESSAGE_LENGTH = 21;
private final PodProgressStatus podProgressStatus; private final PodProgressStatus podProgressStatus;
@ -26,16 +29,13 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
private final Duration timeActive; private final Duration timeActive;
private final AlertSet unacknowledgedAlerts; private final AlertSet unacknowledgedAlerts;
private final boolean faultAccessingTables; private final boolean faultAccessingTables;
private final boolean loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging; private final ErrorEventInfo errorEventInfo;
private final byte loggedFaultEventInternal2bitMainLoopRoutinesVariable;
private final boolean loggedFaultEventImmediateBolusInProgressDuringError;
private final PodProgressStatus loggedFaultEventErrorPodProgressStatus;
private final byte receiverLowGain; private final byte receiverLowGain;
private final byte radioRSSI; private final byte radioRSSI;
private final PodProgressStatus podProgressStatusAtTimeOfFirstLoggedFaultEvent; private final PodProgressStatus previousPodProgressStatus;
private final byte[] unknownValue; private final byte[] unknownValue;
public PodInfoFaultEvent(byte[] encodedData) { public PodInfoDetailedStatus(byte[] encodedData) {
super(encodedData); super(encodedData);
if (encodedData.length < MINIMUM_MESSAGE_LENGTH) { if (encodedData.length < MINIMUM_MESSAGE_LENGTH) {
@ -70,20 +70,33 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
unacknowledgedAlerts = new AlertSet(encodedData[15]); unacknowledgedAlerts = new AlertSet(encodedData[15]);
faultAccessingTables = encodedData[16] == 0x02; faultAccessingTables = encodedData[16] == 0x02;
int loggedFaultEventInfo = ByteUtil.convertUnsignedByteToInt(encodedData[17]); byte rawErrorEventInfo = encodedData[17];
loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging = (loggedFaultEventInfo & 0x80) == 0x80; if (rawErrorEventInfo == 0x00) {
loggedFaultEventInternal2bitMainLoopRoutinesVariable = (byte) ((loggedFaultEventInfo >>> 5) & 0x03); errorEventInfo = null;
loggedFaultEventImmediateBolusInProgressDuringError = (loggedFaultEventInfo & 0x10) == 0x10; } else {
loggedFaultEventErrorPodProgressStatus = PodProgressStatus.fromByte((byte) (loggedFaultEventInfo & 0x0f)); errorEventInfo = ErrorEventInfo.fromByte(rawErrorEventInfo);
}
receiverLowGain = (byte) (ByteUtil.convertUnsignedByteToInt(encodedData[18]) >>> 6); receiverLowGain = (byte) (ByteUtil.convertUnsignedByteToInt(encodedData[18]) >>> 6);
radioRSSI = (byte) (encodedData[18] & 0x3f); 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); unknownValue = ByteUtil.substring(encodedData, 20, 2);
} }
@Override @Override
public PodInfoType getType() { 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() { @Override public PodProgressStatus getPodProgressStatus() {
@ -134,20 +147,8 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
return faultAccessingTables; return faultAccessingTables;
} }
public boolean isLoggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging() { public ErrorEventInfo getErrorEventInfo() {
return loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging; return errorEventInfo;
}
public byte getLoggedFaultEventInternal2bitMainLoopRoutinesVariable() {
return loggedFaultEventInternal2bitMainLoopRoutinesVariable;
}
public boolean isLoggedFaultEventImmediateBolusInProgressDuringError() {
return loggedFaultEventImmediateBolusInProgressDuringError;
}
public PodProgressStatus getLoggedFaultEventErrorPodProgressStatus() {
return loggedFaultEventErrorPodProgressStatus;
} }
public byte getReceiverLowGain() { public byte getReceiverLowGain() {
@ -158,8 +159,8 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
return radioRSSI; return radioRSSI;
} }
public PodProgressStatus getLoggedFaultEventPodProgressStatus() { public PodProgressStatus getPreviousPodProgressStatus() {
return podProgressStatusAtTimeOfFirstLoggedFaultEvent; return previousPodProgressStatus;
} }
public byte[] getUnknownValue() { public byte[] getUnknownValue() {
@ -167,7 +168,7 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
} }
@Override public String toString() { @Override public String toString() {
return "PodInfoFaultEvent{" + return "PodInfoDetailedStatus{" +
"podProgressStatus=" + podProgressStatus + "podProgressStatus=" + podProgressStatus +
", deliveryStatus=" + deliveryStatus + ", deliveryStatus=" + deliveryStatus +
", bolusNotDelivered=" + bolusNotDelivered + ", bolusNotDelivered=" + bolusNotDelivered +
@ -180,14 +181,11 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons
", timeActive=" + timeActive + ", timeActive=" + timeActive +
", unacknowledgedAlerts=" + unacknowledgedAlerts + ", unacknowledgedAlerts=" + unacknowledgedAlerts +
", faultAccessingTables=" + faultAccessingTables + ", faultAccessingTables=" + faultAccessingTables +
", loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging=" + loggedFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging + ", errorEventInfo=" + errorEventInfo +
", loggedFaultEventInternal2bitMainLoopRoutinesVariable=" + loggedFaultEventInternal2bitMainLoopRoutinesVariable +
", loggedFaultEventImmediateBolusInProgressDuringError=" + loggedFaultEventImmediateBolusInProgressDuringError +
", loggedFaultEventErrorPodProgressStatus=" + loggedFaultEventErrorPodProgressStatus +
", receiverLowGain=" + receiverLowGain + ", receiverLowGain=" + receiverLowGain +
", radioRSSI=" + radioRSSI + ", radioRSSI=" + radioRSSI +
", podProgressStatusAtTimeOfFirstLoggedFaultEvent=" + podProgressStatusAtTimeOfFirstLoggedFaultEvent + ", previousPodProgressStatus=" + previousPodProgressStatus +
", unknownValue=" + ByteUtil.shortHexString(unknownValue) + ", 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; import java.util.Locale;
public enum FaultEventCode { public enum FaultEventCode {
NO_FAULTS((byte) 0x00),
FAILED_FLASH_ERASE((byte) 0x01), FAILED_FLASH_ERASE((byte) 0x01),
FAILED_FLASH_STORE((byte) 0x02), FAILED_FLASH_STORE((byte) 0x02),
TABLE_CORRUPTION_BASAL_SUBCOMMAND((byte) 0x03), TABLE_CORRUPTION_BASAL_SUBCOMMAND((byte) 0x03),
@ -129,6 +128,9 @@ public enum FaultEventCode {
} }
public static FaultEventCode fromByte(byte value) { public static FaultEventCode fromByte(byte value) {
if (value == 0x00) { // No faults
return null;
}
for (FaultEventCode type : values()) { for (FaultEventCode type : values()) {
if (type.value == value) { if (type.value == value) {
return type; 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.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.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.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.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.PodInfoOlderPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog;
public enum PodInfoType { public enum PodInfoType {
NORMAL((byte) 0x00), NORMAL((byte) 0x00),
ACTIVE_ALERTS((byte) 0x01), 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. DATA_LOG((byte) 0x03), // Similar to types $50 & $51. Returns up to the last 60 dwords of data.
FAULT_AND_INITIALIZATION_TIME((byte) 0x05), FAULT_AND_INITIALIZATION_TIME((byte) 0x05),
RECENT_PULSE_LOG((byte) 0x50), // Starting at $4200 RECENT_PULSE_LOG((byte) 0x50), // Starting at $4200
@ -44,8 +44,8 @@ public enum PodInfoType {
throw new UnsupportedOperationException("Cannot decode PodInfoType.NORMAL"); throw new UnsupportedOperationException("Cannot decode PodInfoType.NORMAL");
case ACTIVE_ALERTS: case ACTIVE_ALERTS:
return new PodInfoActiveAlerts(encodedData); return new PodInfoActiveAlerts(encodedData);
case FAULT_EVENT: case DETAILED_STATUS:
return new PodInfoFaultEvent(encodedData); return new PodInfoDetailedStatus(encodedData);
case DATA_LOG: case DATA_LOG:
return new PodInfoDataLog(encodedData, bodyLength); return new PodInfoDataLog(encodedData, bodyLength);
case FAULT_AND_INITIALIZATION_TIME: 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; 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 { public class PodFaultException extends OmnipodException {
private final PodInfoFaultEvent faultEvent; private final PodInfoDetailedStatus detailedStatus;
public PodFaultException(PodInfoFaultEvent faultEvent) { public PodFaultException(PodInfoDetailedStatus detailedStatus) {
super(faultEvent.getFaultEventCode().toString(), true); super(detailedStatus.getFaultEventCode().toString(), true);
this.faultEvent = faultEvent; this.detailedStatus = detailedStatus;
} }
public PodInfoFaultEvent getFaultEvent() { public PodInfoDetailedStatus getDetailedStatus() {
return faultEvent; 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.PodInfoType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; 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.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.CommandFailedAfterChangingDeliveryStatusException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalDeliveryStatusException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalDeliveryStatusException;
@ -88,11 +89,18 @@ public class OmnipodManager {
} }
public synchronized Single<Boolean> pairAndPrime() { 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"); logStartingCommandExecution("pairAndPrime");
try { try {
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) {
// Always send both 0x07 and 0x03 on retries // Always send both 0x07 and 0x03 on retries
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) {
try { try {
communicationService.executeAction( communicationService.executeAction(
new AssignAddressAction(podStateManager)); new AssignAddressAction(podStateManager));
@ -109,28 +117,29 @@ public class OmnipodManager {
communicationService.executeAction(new SetupPodAction(podStateManager)); communicationService.executeAction(new SetupPodAction(podStateManager));
} catch (IllegalPacketTypeException ex) { } catch (IllegalPacketTypeException ex) {
if (PacketType.ACK.equals(ex.getActual())) { if (PacketType.ACK.equals(ex.getActual())) {
// TODO is this true for the SetupPodCommand?
// Pod is already configured // Pod is already configured
aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring"); aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring");
} }
} }
} else if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.PRIMING)) { } else {
throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, podStateManager.getPodProgressStatus());
}
// Make sure we have an up to date PodProgressStatus // Make sure we have an up to date PodProgressStatus
getPodStatus(); getPodStatus();
communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager)); if (podStateManager.isPodActivationTimeExceeded()) {
} finally { throw new ActivationTimeExceededException();
logCommandExecutionFinished("pairAndPrime");
} }
}
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(); 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) // return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) //
.map(o -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED)) // .map(o -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED)) //
.subscribeOn(Schedulers.io()); .subscribeOn(Schedulers.io());
} finally {
logCommandExecutionFinished("pairAndPrime");
}
} }
public synchronized Single<Boolean> insertCannula( public synchronized Single<Boolean> insertCannula(
@ -139,26 +148,30 @@ public class OmnipodManager {
throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, !podStateManager.isPodInitialized() ? null : podStateManager.getPodProgressStatus()); 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 + "]"); logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]");
try { try {
communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits)); // Make sure we have the latest PodProgressStatus
} finally { getPodStatus();
logCommandExecutionFinished("insertCannula");
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(); 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) // return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) //
.map(o -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS)) // .map(o -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS)) //
.subscribeOn(Schedulers.io()); .subscribeOn(Schedulers.io());
} finally {
logCommandExecutionFinished("insertCannula");
}
} }
public synchronized StatusResponse getPodStatus() { public synchronized StatusResponse getPodStatus() {
@ -437,7 +450,7 @@ public class OmnipodManager {
break; break;
} catch (PodFaultException ex) { } catch (PodFaultException ex) {
// Subtract units not delivered in case of a Pod failure // 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); aapsLogger.debug(LTag.PUMPCOMM, "Caught PodFaultException in bolus completion verification", ex);
break; break;
@ -473,7 +486,7 @@ public class OmnipodManager {
StatusResponse statusResponse = cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep); StatusResponse statusResponse = cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep);
discardActiveBolusData(statusResponse.getBolusNotDelivered()); discardActiveBolusData(statusResponse.getBolusNotDelivered());
} catch (PodFaultException ex) { } catch (PodFaultException ex) {
discardActiveBolusData(ex.getFaultEvent().getBolusNotDelivered()); discardActiveBolusData(ex.getDetailedStatus().getBolusNotDelivered());
throw ex; throw ex;
} finally { } finally {
logCommandExecutionFinished("cancelBolus"); logCommandExecutionFinished("cancelBolus");

View file

@ -21,11 +21,12 @@ import java.util.function.Supplier;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; 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.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.AlertSet;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot; 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.AlertType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; 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.FirmwareVersion;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodCrc; 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 * @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() { 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 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 * @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 * 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()} * indication on whether or not the pod is faulted, see {@link #isPodFaulted() isPodFaulted()}
*/ */
public final boolean hasFaultEvent() { public final boolean isFaulted() {
return podState != null && podState.getFaultEvent() != null; return podState != null && podState.getFaultEventCode() != null;
} }
public final PodInfoFaultEvent getFaultEvent() { public final FaultEventCode getFaultEventCode() {
return getSafe(() -> podState.getFaultEvent()); return getSafe(() -> podState.getFaultEventCode());
}
public final void setFaultEvent(PodInfoFaultEvent faultEvent) {
setAndStore(() -> podState.setFaultEvent(faultEvent));
} }
public final AlertType getConfiguredAlertType(AlertSlot alertSlot) { 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 * 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(() -> { setSafe(() -> {
if (podState.getActivatedAt() == null) { 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.setActivatedAt(activatedAtCalculated);
} }
podState.setSuspended(statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED); podState.setSuspended(status.getDeliveryStatus() == DeliveryStatus.SUSPENDED);
podState.setActiveAlerts(statusResponse.getUnacknowledgedAlerts()); podState.setActiveAlerts(status.getUnacknowledgedAlerts());
podState.setLastDeliveryStatus(statusResponse.getDeliveryStatus()); podState.setLastDeliveryStatus(status.getDeliveryStatus());
podState.setReservoirLevel(statusResponse.getReservoirLevel()); podState.setReservoirLevel(status.getReservoirLevel());
podState.setTotalTicksDelivered(statusResponse.getTicksDelivered()); podState.setTotalTicksDelivered(status.getTicksDelivered());
podState.setPodProgressStatus(statusResponse.getPodProgressStatus()); podState.setPodProgressStatus(status.getPodProgressStatus());
podState.setTimeActive(statusResponse.getTimeActive()); podState.setTimeActive(status.getTimeActive());
if (statusResponse.getDeliveryStatus().isTbrRunning()) { if (status.getDeliveryStatus().isTbrRunning()) {
if (!isTempBasalCertain() && isTempBasalRunning()) { if (!isTempBasalCertain() && isTempBasalRunning()) {
podState.setTempBasalCertain(true); podState.setTempBasalCertain(true);
} }
@ -535,6 +539,13 @@ public abstract class PodStateManager {
setTempBasal(null, null, null, true, false); setTempBasal(null, null, null, true, false);
} }
podState.setLastUpdatedFromResponse(DateTime.now()); 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 DateTimeZone timeZone;
private DateTime activatedAt; private DateTime activatedAt;
private Duration timeActive; private Duration timeActive;
private PodInfoFaultEvent faultEvent; private FaultEventCode faultEventCode;
private Double reservoirLevel; private Double reservoirLevel;
private Integer totalTicksDelivered; private Integer totalTicksDelivered;
private boolean suspended; private boolean suspended;
@ -751,12 +762,12 @@ public abstract class PodStateManager {
this.timeActive = timeActive; this.timeActive = timeActive;
} }
PodInfoFaultEvent getFaultEvent() { FaultEventCode getFaultEventCode() {
return faultEvent; return faultEventCode;
} }
void setFaultEvent(PodInfoFaultEvent faultEvent) { void setFaultEventCode(FaultEventCode faultEventCode) {
this.faultEvent = faultEvent; this.faultEventCode = faultEventCode;
} }
Double getReservoirLevel() { Double getReservoirLevel() {
@ -930,7 +941,7 @@ public abstract class PodStateManager {
", timeZone=" + timeZone + ", timeZone=" + timeZone +
", activatedAt=" + activatedAt + ", activatedAt=" + activatedAt +
", timeActive=" + timeActive + ", timeActive=" + timeActive +
", faultEvent=" + faultEvent + ", faultEvent=" + faultEventCode +
", reservoirLevel=" + reservoirLevel + ", reservoirLevel=" + reservoirLevel +
", totalTicksDelivered=" + totalTicksDelivered + ", totalTicksDelivered=" + totalTicksDelivered +
", suspended=" + suspended + ", 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.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; 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.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.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalScheduleEntry; 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.CommandFailedAfterChangingDeliveryStatusException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CrcMismatchException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CrcMismatchException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException;
@ -755,11 +755,9 @@ public class AapsOmnipodManager {
if (ex instanceof OmnipodException) { if (ex instanceof OmnipodException) {
aapsLogger.error(LTag.PUMP, String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager", ((OmnipodException) ex).isCertainFailure()), ex); aapsLogger.error(LTag.PUMP, String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager", ((OmnipodException) ex).isCertainFailure()), ex);
if (ex instanceof PodFaultException) { if (ex instanceof PodFaultException) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode(); FaultEventCode faultEventCode = ((PodFaultException) ex).getDetailedStatus().getFaultEventCode();
if (!(faultEventCode == FaultEventCode.NO_FAULTS && podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED)) {
showPodFaultNotification(faultEventCode); showPodFaultNotification(faultEventCode);
} }
}
} else { } else {
aapsLogger.error(LTag.PUMP, "Caught an unexpected non-OmnipodException from OmnipodManager", ex); aapsLogger.error(LTag.PUMP, "Caught an unexpected non-OmnipodException from OmnipodManager", ex);
} }
@ -791,8 +789,10 @@ public class AapsOmnipodManager {
} else if (ex instanceof NotEnoughDataException) { } else if (ex instanceof NotEnoughDataException) {
comment = getStringResource(R.string.omnipod_error_not_enough_data); comment = getStringResource(R.string.omnipod_error_not_enough_data);
} else if (ex instanceof PodFaultException) { } else if (ex instanceof PodFaultException) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode(); FaultEventCode faultEventCode = ((PodFaultException) ex).getDetailedStatus().getFaultEventCode();
comment = createPodFaultErrorMessage(faultEventCode); comment = createPodFaultErrorMessage(faultEventCode);
} else if (ex instanceof ActivationTimeExceededException) {
comment = getStringResource(R.string.omnipod_error_pod_fault_activation_time_exceeded);
} else if (ex instanceof PodReturnedErrorResponseException) { } else if (ex instanceof PodReturnedErrorResponseException) {
comment = getStringResource(R.string.omnipod_error_pod_returned_error_response); comment = getStringResource(R.string.omnipod_error_pod_returned_error_response);
} else if (ex instanceof RileyLinkUnreachableException) { } else if (ex instanceof RileyLinkUnreachableException) {
@ -813,9 +813,6 @@ public class AapsOmnipodManager {
} }
private String createPodFaultErrorMessage(FaultEventCode faultEventCode) { 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, return getStringResource(R.string.omnipod_error_pod_fault,
ByteUtil.convertUnsignedByteToInt(faultEventCode.getValue()), faultEventCode.name()); 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.ErrorResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse; 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.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.communication.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType; 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.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; 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.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.IllegalMessageAddressException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageSequenceNumberException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageSequenceNumberException;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException;
@ -156,12 +157,21 @@ public class OmnipodRileyLinkCommunicationManager extends RileyLinkCommunication
podStateManager.setLastFailedCommunication(DateTime.now()); podStateManager.setLastFailedCommunication(DateTime.now());
throw new PodReturnedErrorResponseException(error); throw new PodReturnedErrorResponseException(error);
} }
} 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.DETAILED_STATUS) {
PodInfoFaultEvent faultEvent = (PodInfoFaultEvent) ((PodInfoResponse) responseMessageBlock).getPodInfo(); PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) ((PodInfoResponse) responseMessageBlock).getPodInfo();
podStateManager.setFaultEvent(faultEvent); if (detailedStatus.isFaulted()) {
// Treat as successful communication as the user will get notified and can work with this response // Treat as successful communication in order to prevent false positive pump unreachable alarms
podStateManager.setLastSuccessfulCommunication(DateTime.now()); 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 { } else {
podStateManager.setLastFailedCommunication(DateTime.now()); podStateManager.setLastFailedCommunication(DateTime.now());
throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType()); throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType());
@ -174,6 +184,7 @@ public class OmnipodRileyLinkCommunicationManager extends RileyLinkCommunication
} finally { } finally {
podStateManager.storePodState(); podStateManager.storePodState();
} }
} }
private MessageBlock transportMessages(PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { private MessageBlock transportMessages(PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) {

View file

@ -272,8 +272,8 @@ class OmnipodOverviewFragment : DaggerFragment() {
}) })
} }
if (podStateManager.hasFaultEvent()) { if (podStateManager.isFaulted) {
val faultEventCode = podStateManager.faultEvent.faultEventCode val faultEventCode = podStateManager.faultEventCode
errors.add(resourceHelper.gs(R.string.omnipod_pod_status_pod_fault_description, faultEventCode.value, faultEventCode.name)) 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) { if (!podStateManager.isPodInitialized) {
resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation) resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation)
} else { } else {
if (PodProgressStatus.ACTIVATION_TIME_EXCEEDED == podStateManager.podProgressStatus) { if (podStateManager.isPodActivationTimeExceeded) {
resourceHelper.gs(R.string.omnipod_pod_status_activation_time_exceeded) resourceHelper.gs(R.string.omnipod_pod_status_activation_time_exceeded)
} else if (podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) { } else if (podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) {
resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation) 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() omnipod_pod_management_waiting_for_rl_layout.visibility = (!rileyLinkServiceData.rileyLinkServiceState.isReady).toVisibility()
if (rileyLinkServiceData.rileyLinkServiceState.isReady) { 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 omnipod_pod_management_button_deactivate_pod.isEnabled = podStateManager.isPodInitialized
if (discardButtonEnabled) { if (discardButtonEnabled) {
omnipod_pod_management_button_discard_pod.isEnabled = true 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.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View 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.driver.manager.PodStateManager
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.common.fragment.ActionFragmentBase import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.common.fragment.ActionFragmentBase
import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.deactivation.PodDeactivationWizardActivity import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.deactivation.PodDeactivationWizardActivity
@ -27,8 +25,7 @@ abstract class PodActivationActionFragmentBase : ActionFragmentBase() {
} }
override fun onActionFailure() { override fun onActionFailure() {
if (podStateManager.isPodInitialized && podStateManager.podProgressStatus == PodProgressStatus.ACTIVATION_TIME_EXCEEDED) { if (podStateManager.isPodActivationTimeExceeded) {
omnipod_wizard_action_error.setText(R.string.omnipod_error_pod_fault_activation_time_exceeded)
omnipod_wizard_button_retry.visibility = View.GONE omnipod_wizard_button_retry.visibility = View.GONE
omnipod_wizard_button_deactivate_pod.visibility = View.VISIBLE 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(activePluginProvider.getActiveTreatments().getTempBasalFromHistory(anyLong())).thenReturn(null);
when(rileyLinkUtil.getRileyLinkHistory()).thenReturn(new ArrayList<>()); when(rileyLinkUtil.getRileyLinkHistory()).thenReturn(new ArrayList<>());
when(injector.androidInjector()).thenReturn(new AndroidInjector<Object>() { when(injector.androidInjector()).thenReturn(new AndroidInjector<Object>() {
@Override public void inject(Object instance) {} @Override public void inject(Object instance) {
}
}); });
Profile profile = mock(Profile.class); Profile profile = mock(Profile.class);

View file

@ -24,7 +24,7 @@ public class GetStatusCommandTest {
@Test @Test
public void testPodInfoTypeFaultEvents() { public void testPodInfoTypeFaultEvents() {
GetStatusCommand getStatusCommand = new GetStatusCommand(PodInfoType.FAULT_EVENT); GetStatusCommand getStatusCommand = new GetStatusCommand(PodInfoType.DETAILED_STATUS);
assertArrayEquals(ByteUtil.fromHexString("0e0102"), getStatusCommand.getRawData()); 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() { public void testMessageDecoding() {
PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d")); 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()); assertFalse(podInfo.isFaultAccessingTables());
assertEquals(0x01, podInfo.getLoggedFaultEventInternal2bitMainLoopRoutinesVariable()); assertEquals(0x01, podInfo.getErrorEventInfo().getInternalVariable());
} }
@Test @Test
public void testInvalidPodInfoTypeMessageDecoding() { public void testInvalidPodInfoTypeMessageDecoding() {
PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d")); PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d"));
assertEquals(PodInfoType.FAULT_EVENT, podInfoResponse.getSubType()); assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType());
thrown.expect(ClassCastException.class); thrown.expect(ClassCastException.class);
PodInfoActiveAlerts podInfo = (PodInfoActiveAlerts) podInfoResponse.getPodInfo(); PodInfoActiveAlerts podInfo = (PodInfoActiveAlerts) podInfoResponse.getPodInfo();