Add GetVersionResponse and SetUniqueIdResponse; add some definitions

This commit is contained in:
Bart Sopers 2021-02-10 00:17:14 +01:00
parent 43409eb864
commit fc4065b71c
15 changed files with 597 additions and 1 deletions

View file

@ -29,7 +29,7 @@ android {
}
dependencies {
implementation 'commons-codec:commons-codec:1.15'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
testImplementation 'junit:junit:4.+'

View file

@ -0,0 +1,4 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod;
public class OmnipodDashManager {
}

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
public interface Command {
CommandType getCommandType();
byte[] getEncoded();
}

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
abstract class CommandBase implements Command {
CommandBase(CommandType commandType) {
}
@Override public CommandType getCommandType() {
return null;
}
}

View file

@ -0,0 +1,26 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
public enum CommandType {
SET_UNIQUE_ID((byte) 0x03),
GET_VERSION((byte) 0x07),
GET_STATUS((byte) 0x0e),
SILENCE_ALERTS((byte) 0x11),
PROGRAM_BASAL((byte) 0x13),
PROGRAM_TEMP_BASAL((byte) 0x16),
BOLUS((byte) 0x17),
PROGRAM_ALERTS((byte) 0x19),
DELIVERY_INTERLOCK((byte) 0x1a),
DEACTIVATE((byte) 0x1c),
PROGRAM_BEEPS((byte) 0x1e),
STOP_DELIVERY((byte) 0x1f);
byte value;
CommandType(byte value) {
this.value = value;
}
public byte getValue() {
return value;
}
}

View file

@ -0,0 +1,26 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
public class OmnipodEvent {
public enum OmnipodEventType {
CONNECTED,
ALREADY_CONNECTED,
FAILED_TO_CONNECT,
DISCONNECTED,
COMMAND_SENT,
GOT_POD_VERSION,
SET_UNIQUE_ID,
PRIMED_PUMP,
FINISHED_ACTIVATION_1,
PROGRAMMED_BASAL,
PROGRAMMED_ALERTS,
SET_BEEPS,
INSERTED_CANNULA,
FINISHED_ACTIVATION_2,
PROGRAMMED_TEMP_BASAL,
STARTED_BOLUS,
STOPPED_DELIVERY,
SILENCED_ALERTS,
DEACTIVATED,
COMMAND_SENDING,
}
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
public enum PodStatus {
UNINITIALIZED((byte) 0x00),
MFG_TEST((byte) 0x01),
FILLED((byte) 0x02),
UID_SET((byte) 0x03),
ENGAGING_CLUTCH_DRIVE((byte) 0x04),
CLUTCH_DRIVE_ENGAGED((byte) 0x05),
BASAL_PROGRAM_RUNNING((byte) 0x06),
PRIMING((byte) 0x07),
RUNNING_ABOVE_MIN_VOLUME((byte) 0x08),
RUNNING_BELOW_MIN_VOLUME((byte) 0x09),
UNUSED_10((byte) 0x0a),
UNUSED_11((byte) 0x0b),
UNUSED_12((byte) 0x0c),
ALARM((byte) 0x0d),
LUMP_OF_COAL((byte) 0x0e),
DEACTIVATED((byte) 0x0f),
UNKNOWN((byte) 0xff);
private byte value;
PodStatus(byte value) {
this.value = value;
}
public static PodStatus byValue(byte value) {
for (PodStatus status : values()) {
if (status.value == value) {
return status;
}
}
return UNKNOWN;
}
}

View file

@ -0,0 +1,14 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
abstract class ActivationResponseBase extends ResponseBase {
final ResponseType.ActivationResponseType activationResponseType;
ActivationResponseBase(ResponseType.ActivationResponseType activationResponseType, byte[] encoded) {
super(ResponseType.ACTIVATION_RESPONSE, encoded);
this.activationResponseType = activationResponseType;
}
public ResponseType.ActivationResponseType getActivationResponseType() {
return activationResponseType;
}
}

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
public interface Response {
ResponseType getResponseType();
byte[] getEncoded();
}

View file

@ -0,0 +1,22 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
import java.util.Arrays;
abstract class ResponseBase implements Response {
final ResponseType responseType;
final byte[] encoded;
ResponseBase(ResponseType responseType, byte[] encoded) {
this.responseType = responseType;
this.encoded = Arrays.copyOf(encoded, encoded.length);
}
@Override public ResponseType getResponseType() {
return responseType;
}
@Override
public byte[] getEncoded() {
return encoded;
}
}

View file

@ -0,0 +1,76 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
public enum ResponseType {
ACTIVATION_RESPONSE((byte) 0x01),
DEFAULT_STATUS_RESPONSE((byte) 0x1d),
ADDITIONAL_STATUS_RESPONSE((byte) 0x02),
NAK_RESPONSE((byte) 0x06),
UNKNOWN((byte) 0xff);
private byte value;
ResponseType(byte value) {
this.value = value;
}
public byte getValue() {
return value;
}
public static ResponseType byValue(byte value) {
for (ResponseType type : values()) {
if (type.value == value) {
return type;
}
}
return UNKNOWN;
}
enum AdditionalStatusResponseType {
STATUS_RESPONSE_PAGE_1((byte) 0x01),
STATUS_RESPONSE_PAGE_2((byte) 0x02),
STATUS_RESPONSE_PAGE_3((byte) 0x03),
STATUS_RESPONSE_PAGE_5((byte) 0x05),
STATUS_RESPONSE_PAGE_6((byte) 0x06),
STATUS_RESPONSE_PAGE_70((byte) 0x46),
STATUS_RESPONSE_PAGE_80((byte) 0x50),
STATUS_RESPONSE_PAGE_81((byte) 0x51),
UNKNOWN((byte) 0xff);
private byte value;
AdditionalStatusResponseType(byte value) {
this.value = value;
}
public static AdditionalStatusResponseType byValue(byte value) {
for (AdditionalStatusResponseType type : values()) {
if (type.value == value) {
return type;
}
}
return UNKNOWN;
}
}
enum ActivationResponseType {
GET_VERSION_RESPONSE((byte) 0x15),
SET_UNIQUE_ID_RESPONSE((byte) 0x1b),
UNKNOWN((byte) 0xff);
private byte length;
ActivationResponseType(byte length) {
this.length = length;
}
public static ActivationResponseType byLength(byte length) {
for (ActivationResponseType type : values()) {
if (type.length == length) {
return type;
}
}
return UNKNOWN;
}
}
}

View file

@ -0,0 +1,155 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
import java.nio.ByteBuffer;
import java.util.Arrays;
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus;
public final class SetUniqueIdResponse extends ActivationResponseBase {
private byte messageType;
private short messageLength;
private short pulseVolumeInTenThousandthMicroLiter;
private short pumpRate;
private short primePumpRate;
private short numberOfEngagingClutchDrivePulses;
private short numberOfPrimePulses;
private short podExpirationTimeInHours;
private short firmwareVersionMajor;
private short firmwareVersionMinor;
private short firmwareVersionInterim;
private short bleVersionMajor;
private short bleVersionMinor;
private short bleVersionInterim;
private short productId;
private PodStatus podStatus;
private long lotNumber;
private long podSequenceNumber;
private long uniqueIdReceivedInCommand;
public SetUniqueIdResponse(byte[] encoded) {
super(ResponseType.ActivationResponseType.SET_UNIQUE_ID_RESPONSE, encoded);
this.messageType = encoded[0];
this.messageLength = (short) (encoded[1] & 0xff);
this.pulseVolumeInTenThousandthMicroLiter = ByteBuffer.wrap(new byte[]{encoded[2], encoded[3]}).getShort();
this.pumpRate = (short) (encoded[4] & 0xff);
this.primePumpRate = (short) (encoded[5] & 0xff);
this.numberOfEngagingClutchDrivePulses = (short) (encoded[6] & 0xff);
this.numberOfPrimePulses = (short) (encoded[7] & 0xff);
this.podExpirationTimeInHours = (short) (encoded[8] & 0xff);
this.firmwareVersionMajor = (short) (encoded[9] & 0xff);
this.firmwareVersionMinor = (short) (encoded[10] & 0xff);
this.firmwareVersionInterim = (short) (encoded[11] & 0xff);
this.bleVersionMajor = (short) (encoded[12] & 0xff);
this.bleVersionMinor = (short) (encoded[13] & 0xff);
this.bleVersionInterim = (short) (encoded[14] & 0xff);
this.productId = (short) (encoded[15] & 0xff);
this.podStatus = PodStatus.byValue(encoded[16]);
this.lotNumber = ByteBuffer.wrap(new byte[]{0, 0, 0, 0, encoded[17], encoded[18], encoded[19], encoded[20]}).getLong();
this.podSequenceNumber = ByteBuffer.wrap(new byte[]{0, 0, 0, 0, encoded[21], encoded[22], encoded[23], encoded[24]}).getLong();
this.uniqueIdReceivedInCommand = ByteBuffer.wrap(new byte[]{0, 0, 0, 0, encoded[25], encoded[26], encoded[27], encoded[28]}).getLong();
}
public byte getMessageType() {
return messageType;
}
public short getMessageLength() {
return messageLength;
}
public short getPulseVolumeInTenThousandthMicroLiter() {
return pulseVolumeInTenThousandthMicroLiter;
}
public short getDeliveryRate() {
return pumpRate;
}
public short getPrimeRate() {
return primePumpRate;
}
public short getNumberOfEngagingClutchDrivePulses() {
return numberOfEngagingClutchDrivePulses;
}
public short getNumberOfPrimePulses() {
return numberOfPrimePulses;
}
public short getPodExpirationTimeInHours() {
return podExpirationTimeInHours;
}
public short getFirmwareVersionMajor() {
return firmwareVersionMajor;
}
public short getFirmwareVersionMinor() {
return firmwareVersionMinor;
}
public short getFirmwareVersionInterim() {
return firmwareVersionInterim;
}
public short getBleVersionMajor() {
return bleVersionMajor;
}
public short getBleVersionMinor() {
return bleVersionMinor;
}
public short getBleVersionInterim() {
return bleVersionInterim;
}
public short getProductId() {
return productId;
}
public PodStatus getPodStatus() {
return podStatus;
}
public long getLotNumber() {
return lotNumber;
}
public long getPodSequenceNumber() {
return podSequenceNumber;
}
public long getUniqueIdReceivedInCommand() {
return uniqueIdReceivedInCommand;
}
@Override public String toString() {
return "SetUniqueIdResponse{" +
"messageType=" + messageType +
", messageLength=" + messageLength +
", pulseVolume=" + pulseVolumeInTenThousandthMicroLiter +
", pumpRate=" + pumpRate +
", primePumpRate=" + primePumpRate +
", numberOfEngagingClutchDrivePulses=" + numberOfEngagingClutchDrivePulses +
", numberOfPrimePulses=" + numberOfPrimePulses +
", podExpirationTimeInHours=" + podExpirationTimeInHours +
", softwareVersionMajor=" + firmwareVersionMajor +
", softwareVersionMinor=" + firmwareVersionMinor +
", softwareVersionInterim=" + firmwareVersionInterim +
", bleVersionMajor=" + bleVersionMajor +
", bleVersionMinor=" + bleVersionMinor +
", bleVersionInterim=" + bleVersionInterim +
", productId=" + productId +
", podStatus=" + podStatus +
", lotNumber=" + lotNumber +
", podSequenceNumber=" + podSequenceNumber +
", uniqueIdReceivedInCommand=" + uniqueIdReceivedInCommand +
", activationResponseType=" + activationResponseType +
", responseType=" + responseType +
", encoded=" + Arrays.toString(encoded) +
'}';
}
}

View file

@ -0,0 +1,128 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
import java.nio.ByteBuffer;
import java.util.Arrays;
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus;
public final class VersionResponse extends ActivationResponseBase {
private final byte messageType;
private final short messageLength;
private final short firmwareVersionMajor;
private final short firmwareVersionMinor;
private final short firmwareVersionInterim;
private final short bleVersionMajor;
private final short bleVersionMinor;
private final short bleVersionInterim;
private final short productId;
private final PodStatus podStatus;
private final long lotNumber;
private final long podSequenceNumber;
private final byte rssi;
private final byte receiverLowerGain;
private final long uniqueIdReceivedInCommand;
public VersionResponse(byte[] encoded) {
super(ResponseType.ActivationResponseType.GET_VERSION_RESPONSE, encoded);
messageType = encoded[0];
messageLength = (short) (encoded[1] & 0xff);
firmwareVersionMajor = (short) (encoded[2] & 0xff);
firmwareVersionMinor = (short) (encoded[3] & 0xff);
firmwareVersionInterim = (short) (encoded[4] & 0xff);
bleVersionMajor = (short) (encoded[5] & 0xff);
bleVersionMinor = (short) (encoded[6] & 0xff);
bleVersionInterim = (short) (encoded[7] & 0xff);
productId = (short) (encoded[8] & 0xff);
podStatus = PodStatus.byValue((byte) (encoded[9] & 0xf));
lotNumber = ByteBuffer.wrap(new byte[]{0, 0, 0, 0, encoded[10], encoded[11], encoded[12], encoded[13]}).getLong();
podSequenceNumber = ByteBuffer.wrap(new byte[]{0, 0, 0, 0, encoded[14], encoded[15], encoded[16], encoded[17]}).getLong();
rssi = (byte) (encoded[18] & 0x3f);
receiverLowerGain = (byte) ((encoded[18] >> 6) & 0x03);
uniqueIdReceivedInCommand = ByteBuffer.wrap(new byte[]{0, 0, 0, 0, encoded[19], encoded[20], encoded[21], encoded[22]}).getLong();
}
public byte getMessageType() {
return messageType;
}
public short getMessageLength() {
return messageLength;
}
public short getFirmwareVersionMajor() {
return firmwareVersionMajor;
}
public short getFirmwareVersionMinor() {
return firmwareVersionMinor;
}
public short getFirmwareVersionInterim() {
return firmwareVersionInterim;
}
public short getBleVersionMajor() {
return bleVersionMajor;
}
public short getBleVersionMinor() {
return bleVersionMinor;
}
public short getBleVersionInterim() {
return bleVersionInterim;
}
public short getProductId() {
return productId;
}
public PodStatus getPodStatus() {
return podStatus;
}
public long getLotNumber() {
return lotNumber;
}
public long getPodSequenceNumber() {
return podSequenceNumber;
}
public byte getRssi() {
return rssi;
}
public byte getReceiverLowerGain() {
return receiverLowerGain;
}
public long getUniqueIdReceivedInCommand() {
return uniqueIdReceivedInCommand;
}
@Override public String toString() {
return "VersionResponse{" +
"messageType=" + messageType +
", messageLength=" + messageLength +
", firmwareVersionMajor=" + firmwareVersionMajor +
", firmwareVersionMinor=" + firmwareVersionMinor +
", firmwareVersionInterim=" + firmwareVersionInterim +
", bleVersionMajor=" + bleVersionMajor +
", bleVersionMinor=" + bleVersionMinor +
", bleVersionInterim=" + bleVersionInterim +
", productId=" + productId +
", podStatus=" + podStatus +
", lotNumber=" + lotNumber +
", podSequenceNumber=" + podSequenceNumber +
", rssi=" + rssi +
", receiverLowerGain=" + receiverLowerGain +
", uniqueIdReceivedInCommand=" + uniqueIdReceivedInCommand +
", activationResponseType=" + activationResponseType +
", responseType=" + responseType +
", encoded=" + Arrays.toString(encoded) +
'}';
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.junit.Test;
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
public class SetUniqueIdResponseTest {
@Test
public void testValidResponse() throws DecoderException {
byte[] encoded = Hex.decodeHex("011B13881008340A50040A00010300040308146CC1000954D402420001");
SetUniqueIdResponse response = new SetUniqueIdResponse(encoded);
assertArrayEquals(encoded, response.getEncoded());
assertNotSame(encoded, response.getEncoded());
assertEquals(ResponseType.ACTIVATION_RESPONSE, response.getResponseType());
assertEquals(ResponseType.ActivationResponseType.SET_UNIQUE_ID_RESPONSE, response.getActivationResponseType());
assertEquals(ResponseType.ACTIVATION_RESPONSE.getValue(), response.getMessageType());
assertEquals(27, response.getMessageLength());
assertEquals(5000, response.getPulseVolumeInTenThousandthMicroLiter());
assertEquals(16, response.getDeliveryRate());
assertEquals(8, response.getPrimeRate());
assertEquals(52, response.getNumberOfEngagingClutchDrivePulses());
assertEquals(10, response.getNumberOfPrimePulses());
assertEquals(80, response.getPodExpirationTimeInHours());
assertEquals(4, response.getFirmwareVersionMajor());
assertEquals(10, response.getFirmwareVersionMinor());
assertEquals(0, response.getFirmwareVersionInterim());
assertEquals(1, response.getBleVersionMajor());
assertEquals(3, response.getBleVersionMinor());
assertEquals(0, response.getBleVersionInterim());
assertEquals(4, response.getProductId());
assertEquals(PodStatus.UID_SET, response.getPodStatus());
assertEquals(135556289L, response.getLotNumber());
assertEquals(611540L, response.getPodSequenceNumber());
assertEquals(37879809L, response.getUniqueIdReceivedInCommand());
}
}

View file

@ -0,0 +1,41 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.junit.Test;
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
public class VersionResponseTest {
@Test
public void testValidResponse() throws DecoderException {
byte[] encoded = Hex.decodeHex("0115040A00010300040208146CC1000954D400FFFFFFFF");
VersionResponse response = new VersionResponse(encoded);
assertArrayEquals(encoded, response.getEncoded());
assertNotSame(encoded, response.getEncoded());
assertEquals(ResponseType.ACTIVATION_RESPONSE, response.getResponseType());
assertEquals(ResponseType.ActivationResponseType.GET_VERSION_RESPONSE, response.getActivationResponseType());
assertEquals(ResponseType.ACTIVATION_RESPONSE.getValue(), response.getMessageType());
assertEquals(21, response.getMessageLength());
assertEquals(4, response.getFirmwareVersionMajor());
assertEquals(10, response.getFirmwareVersionMinor());
assertEquals(0, response.getFirmwareVersionInterim());
assertEquals(1, response.getBleVersionMajor());
assertEquals(3, response.getBleVersionMinor());
assertEquals(0, response.getBleVersionInterim());
assertEquals(4, response.getProductId());
assertEquals(PodStatus.FILLED, response.getPodStatus());
assertEquals(135556289, response.getLotNumber());
assertEquals(611540, response.getPodSequenceNumber());
assertEquals(0L, response.getRssi());
assertEquals(0L, response.getReceiverLowerGain());
assertEquals(4294967295L, response.getUniqueIdReceivedInCommand());
}
}