Add SetUniqueIdCommand and DeactivateCommand; add captures for ProgramAlertsCommand
This commit is contained in:
parent
f1d095d9c8
commit
af35253f0b
7 changed files with 230 additions and 12 deletions
|
@ -8,22 +8,36 @@ import java.util.List;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.CrcUtil;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.CrcUtil;
|
||||||
|
|
||||||
abstract class CommandBase implements Command {
|
abstract class CommandBase implements Command {
|
||||||
final CommandType commandType;
|
static final short HEADER_LENGTH = 6;
|
||||||
final short sequenceNumber;
|
|
||||||
|
|
||||||
CommandBase(CommandType commandType, short sequenceNumber) {
|
final CommandType commandType;
|
||||||
|
final int address;
|
||||||
|
final short sequenceNumber;
|
||||||
|
final boolean unknown;
|
||||||
|
|
||||||
|
CommandBase(CommandType commandType, int address, short sequenceNumber, boolean unknown) {
|
||||||
this.commandType = commandType;
|
this.commandType = commandType;
|
||||||
|
this.address = address;
|
||||||
this.sequenceNumber = sequenceNumber;
|
this.sequenceNumber = sequenceNumber;
|
||||||
|
this.unknown = unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public CommandType getCommandType() {
|
@Override public CommandType getCommandType() {
|
||||||
return commandType;
|
return commandType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
public short getSequenceNumber() {
|
public short getSequenceNumber() {
|
||||||
return sequenceNumber;
|
return sequenceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUnknown() {
|
||||||
|
return unknown;
|
||||||
|
}
|
||||||
|
|
||||||
static byte[] formatCommand(byte[] command) {
|
static byte[] formatCommand(byte[] command) {
|
||||||
List<Byte> temp = new ArrayList<>();
|
List<Byte> temp = new ArrayList<>();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class DeactivateCommand extends CommandBase {
|
||||||
|
private static final short LENGTH = 6;
|
||||||
|
private static final byte BODY_LENGTH = 4;
|
||||||
|
|
||||||
|
DeactivateCommand(int address, short sequenceNumber, boolean unknown) {
|
||||||
|
super(CommandType.DEACTIVATE, address, sequenceNumber, unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public byte[] getEncoded() {
|
||||||
|
return appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
|
.put(encodeHeader(address, sequenceNumber, LENGTH, unknown)) //
|
||||||
|
.put(commandType.getValue()) //
|
||||||
|
.put(BODY_LENGTH) //
|
||||||
|
.putInt(1229869870) // FIXME ?? was: byte array of int 777211465 converted to little endian
|
||||||
|
.array());
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,21 +7,16 @@ public class GetVersionCommand extends CommandBase {
|
||||||
private static final short LENGTH = 6;
|
private static final short LENGTH = 6;
|
||||||
private static final byte BODY_LENGTH = 4;
|
private static final byte BODY_LENGTH = 4;
|
||||||
|
|
||||||
private final int address;
|
|
||||||
private final boolean unknown;
|
|
||||||
|
|
||||||
public GetVersionCommand(short sequenceNumber, boolean unknown) {
|
public GetVersionCommand(short sequenceNumber, boolean unknown) {
|
||||||
this(sequenceNumber, DEFAULT_ADDRESS, unknown);
|
this(DEFAULT_ADDRESS, sequenceNumber, unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetVersionCommand(short sequenceNumber, int address, boolean unknown) {
|
public GetVersionCommand(int address, short sequenceNumber, boolean unknown) {
|
||||||
super(CommandType.GET_VERSION, sequenceNumber);
|
super(CommandType.GET_VERSION, address, sequenceNumber, unknown);
|
||||||
this.address = address;
|
|
||||||
this.unknown = unknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public byte[] getEncoded() {
|
@Override public byte[] getEncoded() {
|
||||||
return appendCrc(ByteBuffer.allocate(12) //
|
return appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(address, sequenceNumber, LENGTH, unknown)) //
|
.put(encodeHeader(address, sequenceNumber, LENGTH, unknown)) //
|
||||||
.put(commandType.getValue()) //
|
.put(commandType.getValue()) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class SetUniqueIdCommand extends CommandBase {
|
||||||
|
private static final int DEFAULT_ADDRESS = -1;
|
||||||
|
private static final short LENGTH = 21;
|
||||||
|
private static final byte BODY_LENGTH = 19;
|
||||||
|
|
||||||
|
private final int lotNumber;
|
||||||
|
private final int podSequenceNumber;
|
||||||
|
private final Date initializationTime;
|
||||||
|
|
||||||
|
SetUniqueIdCommand(int address, short sequenceNumber, int lotNumber, int podSequenceNumber, Date initializationTime, boolean unknown) {
|
||||||
|
super(CommandType.SET_UNIQUE_ID, address, sequenceNumber, unknown);
|
||||||
|
this.lotNumber = lotNumber;
|
||||||
|
this.podSequenceNumber = podSequenceNumber;
|
||||||
|
this.initializationTime = initializationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public byte[] getEncoded() {
|
||||||
|
return appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
|
.put(encodeHeader(DEFAULT_ADDRESS, sequenceNumber, LENGTH, unknown)) //
|
||||||
|
.put(commandType.getValue()) //
|
||||||
|
.put(BODY_LENGTH) //
|
||||||
|
.putInt(address) //
|
||||||
|
.put((byte) 0x14) // FIXME ??
|
||||||
|
.put((byte) 0x04) // FIXME ??
|
||||||
|
.put(encodeInitializationTime(initializationTime)) //
|
||||||
|
.putInt(lotNumber) //
|
||||||
|
.putInt(podSequenceNumber) //
|
||||||
|
.array());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] encodeInitializationTime(Date date) {
|
||||||
|
Calendar instance = Calendar.getInstance();
|
||||||
|
instance.setTime(date);
|
||||||
|
|
||||||
|
return new byte[]{ //
|
||||||
|
(byte) (instance.get(Calendar.MONTH) + 1), //
|
||||||
|
(byte) instance.get(Calendar.DATE), //
|
||||||
|
(byte) (instance.get(Calendar.YEAR) % 100), //
|
||||||
|
(byte) instance.get(Calendar.HOUR_OF_DAY), //
|
||||||
|
(byte) instance.get(Calendar.MINUTE) //
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.DecoderException;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
public class DeactivateCommandTest {
|
||||||
|
@Test
|
||||||
|
public void testEncoding() throws DecoderException {
|
||||||
|
byte[] encoded = new DeactivateCommand(37879809, (short) 5, false) //
|
||||||
|
.getEncoded();
|
||||||
|
|
||||||
|
assertArrayEquals(Hex.decodeHex("0242000114061C04494E532E001C"), encoded);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
|
public class ProgramAlertsCommandTest {
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// Address for all captures below: 37879811
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pod expiration alerts
|
||||||
|
|
||||||
|
V/PodComm: *** encode() CALLED ON ProgramAlertsCommandEncoder
|
||||||
|
*** encode() CALLED ON HeaderEncoder
|
||||||
|
V/PodComm: *** encode() RESULT FOR HeaderEncoder: 02:42:00:03:8C:12 FROM HeaderEncoder{lengthSequenceNumberAndFlags=-29678, f6666a=[], encoded=[2, 66, 0, 3, -116, 18], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}
|
||||||
|
*** encode() RESULT FOR ProgramAlertsCommandEncoder: 02:42:00:03:8C:12:19:10:49:4E:53:2E:79:A4:10:D1:05:02:28:00:12:75:06:02:80:F5 FROM ProgramAlertsCommandEncoder{parameters=ProgramAlertsCommandParameters{configurations=[AlertConfigurationEncoder{slot=7, enabled=true, durationInMinutes=420, autoOff=false, timeTrigger=false, offsetInMinutes=4305, beepType=2, beepRepetition=5}, AlertConfigurationEncoder{slot=2, enabled=true, durationInMinutes=0, autoOff=false, timeTrigger=false, offsetInMinutes=4725, beepType=2, beepRepetition=6}]}, f6666a=[], encoded=[2, 66, 0, 3, -116, 18, 25, 16, 73, 78, 83, 46, 121, -92, 16, -47, 5, 2, 40, 0, 18, 117, 6, 2, -128, -11], headerEncoder=HeaderEncoder{lengthSequenceNumberAndFlags=-29678, f6666a=[], encoded=[2, 66, 0, 3, -116, 18], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}, commandId=25, f6671f=0, commandBodyLength=16}
|
||||||
|
|
||||||
|
I/PodComm: pod command: 024200038C121910494E532E79A410D1050228001275060280F5
|
||||||
|
V/PodComm: flags: seqNum=3 ack=false mctf=true
|
||||||
|
Program Alert:
|
||||||
|
length:16, number of alerts:2
|
||||||
|
-------------------------------------
|
||||||
|
alert index: 7 (lump of coal/pod expiration)
|
||||||
|
enabled: true
|
||||||
|
duration: 420 minutes
|
||||||
|
set alarm: false
|
||||||
|
V/PodComm: type: time - trigger after 4305 minutes (71.75 hrs)
|
||||||
|
beep type: 2
|
||||||
|
beep repetition: 5
|
||||||
|
-------------------------------------
|
||||||
|
alert index: 2 (imminent pod expiration)
|
||||||
|
enabled: true
|
||||||
|
duration: 0 minutes
|
||||||
|
set alarm: false
|
||||||
|
type: time - trigger after 4725 minutes (78.75 hrs)
|
||||||
|
beep type: 2
|
||||||
|
beep repetition: 6
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Low reservoir
|
||||||
|
|
||||||
|
V/PodComm: *** encode() RESULT FOR HeaderEncoder: 02:42:00:03:20:0C FROM HeaderEncoder{lengthSequenceNumberAndFlags=8204, f6666a=[], encoded=[2, 66, 0, 3, 32, 12], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}
|
||||||
|
V/PodComm: *** encode() RESULT FOR ProgramAlertsCommandEncoder: 02:42:00:03:20:0C:19:0A:49:4E:53:2E:4C:00:00:C8:01:02:01:49 FROM ProgramAlertsCommandEncoder{parameters=ProgamAlertsCommandParameters{configurations=[AlertConfigurationEncoder{slot=4, enabled=true, durationInMinutes=0, autoOff=false, timeTrigger=true, offsetInMinutes=200, beepType=2, beepRepetition=1}]}, f6666a=[], encoded=[2, 66, 0, 3, 32, 12, 25, 10, 73, 78, 83, 46, 76, 0, 0, -56, 1, 2, 1, 73], headerEncoder=HeaderEncoder{lengthSequenceNumberAndFlags=8204, f6666a=[], encoded=[2, 66, 0, 3, 32, 12], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}, commandId=25, f6671f=0, commandBodyLength=10}
|
||||||
|
|
||||||
|
V/PodComm: flags: seqNum=8 ack=false mctf=false
|
||||||
|
Program Alert:
|
||||||
|
length:10, number of alerts:1
|
||||||
|
-------------------------------------
|
||||||
|
alert index: 4 (low reservoir)
|
||||||
|
enabled: true
|
||||||
|
duration: 0 minutes
|
||||||
|
set alarm: false
|
||||||
|
type: volume - trigger at 200 micro liter
|
||||||
|
beep type: 2
|
||||||
|
beep repetition: 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
User Pod expiration
|
||||||
|
|
||||||
|
V/PodComm: *** encode() CALLED ON ProgramAlertsCommandEncoder
|
||||||
|
*** encode() CALLED ON HeaderEncoder
|
||||||
|
V/PodComm: *** encode() RESULT FOR HeaderEncoder: 02:42:00:03:3C:0C FROM HeaderEncoder{lengthSequenceNumberAndFlags=15372, f6666a=[], encoded=[2, 66, 0, 3, 60, 12], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}
|
||||||
|
V/PodComm: *** encode() RESULT FOR ProgramAlertsCommandEncoder: 02:42:00:03:3C:0C:19:0A:49:4E:53:2E:38:00:0F:EF:03:02:03:E2 FROM ProgramAlertsCommandEncoder{parameters=ProgramAlertsCommandParameters{configurations=[AlertConfigurationEncoder{slot=3, enabled=true, durationInMinutes=0, autoOff=false, timeTrigger=false, offsetInMinutes=4079, beepType=2, beepRepetition=3}]}, f6666a=[], encoded=[2, 66, 0, 3, 60, 12, 25, 10, 73, 78, 83, 46, 56, 0, 15, -17, 3, 2, 3, -30], headerEncoder=HeaderEncoder{lengthSequenceNumberAndFlags=15372, f6666a=[], encoded=[2, 66, 0, 3, 60, 12], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}, commandId=25, f6671f=0, commandBodyLength=10}
|
||||||
|
|
||||||
|
I/PodComm: pod command: 024200033C0C190A494E532E38000FEF030203E2
|
||||||
|
V/PodComm: flags: seqNum=15 ack=false mctf=false
|
||||||
|
Program Alert:
|
||||||
|
length:10, number of alerts:1
|
||||||
|
-------------------------------------
|
||||||
|
alert index: 3 (user pod expiration)
|
||||||
|
enabled: true
|
||||||
|
duration: 0 minutes
|
||||||
|
set alarm: false
|
||||||
|
type: time - trigger after 4079 minutes (67.98 hrs)
|
||||||
|
beep type: 2
|
||||||
|
beep repetition: 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Lump of coal
|
||||||
|
|
||||||
|
V/PodComm: *** encode() CALLED ON ProgramAlertsCommandEncoder
|
||||||
|
*** encode() CALLED ON HeaderEncoder
|
||||||
|
*** encode() RESULT FOR HeaderEncoder: 02:42:00:03:28:0C FROM HeaderEncoder{lengthSequenceNumberAndFlags=10252, f6666a=[], encoded=[2, 66, 0, 3, 40, 12], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}
|
||||||
|
D/MainActivity: Pod Activation 1: got Pod Event
|
||||||
|
V/PodComm: *** encode() RESULT FOR ProgramAlertsCommandEncoder: 02:42:00:03:28:0C:19:0A:49:4E:53:2E:78:37:00:05:08:02:03:56 FROM ProgramAlertsCommandEncoder{parameters=ProgramAlertsCommandParameters{configurations=[AlertConfigurationEncoder{slot=7, enabled=true, durationInMinutes=55, autoOff=false, timeTrigger=false, offsetInMinutes=5, beepType=2, beepRepetition=8}]}, f6666a=[], encoded=[2, 66, 0, 3, 40, 12, 25, 10, 73, 78, 83, 46, 120, 55, 0, 5, 8, 2, 3, 86], headerEncoder=HeaderEncoder{lengthSequenceNumberAndFlags=10252, f6666a=[], encoded=[2, 66, 0, 3, 40, 12], headerEncoder=null, commandId=0, f6671f=0, commandBodyLength=0}, commandId=25, f6671f=0, commandBodyLength=10}
|
||||||
|
|
||||||
|
V/PodComm: flags: seqNum=10 ack=false mctf=false
|
||||||
|
Program Alert:
|
||||||
|
length:10, number of alerts:1
|
||||||
|
-------------------------------------
|
||||||
|
V/PodComm: alert index: 7 (lump of coal/pod expiration)
|
||||||
|
enabled: true
|
||||||
|
duration: 55 minutes
|
||||||
|
set alarm: false
|
||||||
|
type: time - trigger after 5 minutes (0.08 hrs)
|
||||||
|
beep type: 2
|
||||||
|
beep repetition: 8
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.DecoderException;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
public class SetUniqueIdCommandTest {
|
||||||
|
@Test
|
||||||
|
public void testEncoding() throws DecoderException {
|
||||||
|
byte[] encoded = new SetUniqueIdCommand(37879811, (short) 6, 135556289, 681767, new Date(2021, 1, 10, 14, 41), false) //
|
||||||
|
.getEncoded();
|
||||||
|
|
||||||
|
assertArrayEquals(Hex.decodeHex("FFFFFFFF18150313024200031404020A150E2908146CC1000A67278344"), encoded);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue