Add ProgramAlertsCommand
This commit is contained in:
parent
af35253f0b
commit
eb46c973a3
|
@ -78,7 +78,7 @@ abstract class CommandBase implements Command {
|
|||
static byte[] encodeHeader(int address, short sequenceNumber, short length, boolean unknown) {
|
||||
return ByteBuffer.allocate(6) //
|
||||
.putInt(address) //
|
||||
.putShort((short) (((sequenceNumber & 15) << 10) | length | (((unknown ? 1 : 0) & 1) << 15))) //
|
||||
.putShort((short) (((sequenceNumber & 0x0f) << 10) | length | ((unknown ? 1 : 0) << 15))) //
|
||||
.array();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,13 @@ public class DeactivateCommand extends CommandBase {
|
|||
.putInt(1229869870) // FIXME ?? was: byte array of int 777211465 converted to little endian
|
||||
.array());
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "DeactivateCommand{" +
|
||||
"commandType=" + commandType +
|
||||
", address=" + address +
|
||||
", sequenceNumber=" + sequenceNumber +
|
||||
", unknown=" + unknown +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,4 +23,13 @@ public class GetVersionCommand extends CommandBase {
|
|||
.putInt(address) //
|
||||
.array());
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "GetVersionCommand{" +
|
||||
"commandType=" + commandType +
|
||||
", address=" + address +
|
||||
", sequenceNumber=" + sequenceNumber +
|
||||
", unknown=" + unknown +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration;
|
||||
|
||||
public class ProgramAlertsCommand extends CommandBase {
|
||||
private final List<AlertConfiguration> alertConfigurations;
|
||||
|
||||
ProgramAlertsCommand(int address, short sequenceNumber, boolean unknown, List<AlertConfiguration> alertConfigurations) {
|
||||
super(CommandType.PROGRAM_ALERTS, address, sequenceNumber, unknown);
|
||||
this.alertConfigurations = new ArrayList<>(alertConfigurations);
|
||||
}
|
||||
|
||||
@Override public byte[] getEncoded() {
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(getLength() + HEADER_LENGTH) //
|
||||
.put(encodeHeader(address, sequenceNumber, getLength(), unknown)) //
|
||||
.put(commandType.getValue()) //
|
||||
.put(getBodyLength()) //
|
||||
.putInt(1229869870); // FIXME ?? was: byte array of int 777211465 converted to little endian
|
||||
for (AlertConfiguration configuration : alertConfigurations) {
|
||||
byteBuffer.put(configuration.getEncoded());
|
||||
}
|
||||
return appendCrc(byteBuffer.array());
|
||||
}
|
||||
|
||||
private short getLength() {
|
||||
return (short) (alertConfigurations.size() * 6 + 6);
|
||||
}
|
||||
|
||||
private byte getBodyLength() {
|
||||
return (byte) (alertConfigurations.size() * 6 + 4);
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "ProgramAlertsCommand{" +
|
||||
"alertConfigurations=" + alertConfigurations +
|
||||
", commandType=" + commandType +
|
||||
", address=" + address +
|
||||
", sequenceNumber=" + sequenceNumber +
|
||||
", unknown=" + unknown +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -47,4 +47,16 @@ public class SetUniqueIdCommand extends CommandBase {
|
|||
(byte) instance.get(Calendar.MINUTE) //
|
||||
};
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "SetUniqueIdCommand{" +
|
||||
"lotNumber=" + lotNumber +
|
||||
", podSequenceNumber=" + podSequenceNumber +
|
||||
", initializationTime=" + initializationTime +
|
||||
", commandType=" + commandType +
|
||||
", address=" + address +
|
||||
", sequenceNumber=" + sequenceNumber +
|
||||
", unknown=" + unknown +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class AlertConfiguration {
|
||||
private AlertSlot slot;
|
||||
private boolean enabled;
|
||||
private short durationInMinutes;
|
||||
private boolean autoOff;
|
||||
private AlertTriggerType triggerType;
|
||||
private short offsetInMinutesOrThresholdInMicroLiters;
|
||||
private BeepType beepType;
|
||||
private BeepRepetitionType beepRepetition;
|
||||
|
||||
public AlertConfiguration(AlertSlot slot, boolean enabled, short durationInMinutes, boolean autoOff, AlertTriggerType triggerType, short offsetInMinutesOrThresholdInMicroLiters, BeepType beepType, BeepRepetitionType beepRepetition) {
|
||||
this.slot = slot;
|
||||
this.enabled = enabled;
|
||||
this.durationInMinutes = durationInMinutes;
|
||||
this.autoOff = autoOff;
|
||||
this.triggerType = triggerType;
|
||||
this.offsetInMinutesOrThresholdInMicroLiters = offsetInMinutesOrThresholdInMicroLiters;
|
||||
this.beepType = beepType;
|
||||
this.beepRepetition = beepRepetition;
|
||||
}
|
||||
|
||||
/* renamed from: d */
|
||||
public byte[] getEncoded() {
|
||||
byte firstByte = (byte) (slot.getValue() << 4);
|
||||
if (enabled) {
|
||||
firstByte |= 1 << 3;
|
||||
}
|
||||
if (triggerType == AlertTriggerType.RESERVOIR_VOLUME_TRIGGER) {
|
||||
firstByte |= 1 << 2;
|
||||
}
|
||||
if (autoOff) {
|
||||
firstByte |= 1 << 1;
|
||||
}
|
||||
firstByte |= ((durationInMinutes >> 8) & 0x01);
|
||||
|
||||
return ByteBuffer.allocate(6) //
|
||||
.put(firstByte)
|
||||
.put((byte) durationInMinutes) //
|
||||
.putShort(offsetInMinutesOrThresholdInMicroLiters) //
|
||||
.put(beepRepetition.getValue()) //
|
||||
.put(beepType.getValue()) //
|
||||
.array();
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "AlertConfiguration{" +
|
||||
"slot=" + slot +
|
||||
", enabled=" + enabled +
|
||||
", durationInMinutes=" + durationInMinutes +
|
||||
", autoOff=" + autoOff +
|
||||
", triggerType=" + triggerType +
|
||||
", offsetInMinutesOrThresholdInMicroLiters=" + offsetInMinutesOrThresholdInMicroLiters +
|
||||
", beepType=" + beepType +
|
||||
", beepRepetition=" + beepRepetition +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
|
||||
|
||||
public enum AlertSlot {
|
||||
EXPIRATION_IMMINENT((byte) 0x02),
|
||||
LOW_RESERVOIR((byte) 0x04),
|
||||
USER_POD_EXPIRATION((byte) 0x03),
|
||||
LUMP_OF_COAL_AND_EXPIRATION((byte) 0x07),
|
||||
UNKNOWN((byte) 255);
|
||||
|
||||
private byte value;
|
||||
|
||||
AlertSlot(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static AlertSlot byValue(byte value) {
|
||||
for (AlertSlot slot : values()) {
|
||||
if (slot.value == value) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
|
||||
|
||||
public enum AlertTriggerType {
|
||||
TIME_TRIGGER,
|
||||
RESERVOIR_VOLUME_TRIGGER
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
|
||||
|
||||
// FIXME names
|
||||
public enum BeepRepetitionType {
|
||||
XXX((byte) 0x01), // Used in low reservoir alert
|
||||
XXX2((byte) 0x03), // Used in user pod expiration alert
|
||||
XXX3((byte) 0x05), // Used in pod expiration alert
|
||||
XXX4((byte) 0x06), // Used in imminent pod expiration alert
|
||||
XXX5((byte) 0x08); // Used in lump of coal alert
|
||||
|
||||
private byte value;
|
||||
|
||||
BeepRepetitionType(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition;
|
||||
|
||||
// FIXME names
|
||||
public enum BeepType {
|
||||
SILENT((byte) 0x00),
|
||||
XXX((byte) 0x02); //// Used in low reservoir alert, user expiration alert, expiration alert, imminent expiration alert, lump of coal alert
|
||||
|
||||
private byte value;
|
||||
|
||||
BeepType(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -1,102 +1,60 @@
|
|||
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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration;
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot;
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTriggerType;
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType;
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
public class ProgramAlertsCommandTest {
|
||||
// TODO
|
||||
@Test
|
||||
public void testExpirationAlerts() throws DecoderException {
|
||||
List<AlertConfiguration> configurations = new ArrayList<>();
|
||||
configurations.add(new AlertConfiguration(AlertSlot.LUMP_OF_COAL_AND_EXPIRATION, true, (short) 420, false, AlertTriggerType.TIME_TRIGGER, (short) 4305, BeepType.XXX, BeepRepetitionType.XXX3));
|
||||
configurations.add(new AlertConfiguration(AlertSlot.EXPIRATION_IMMINENT, true, (short) 0, false, AlertTriggerType.TIME_TRIGGER, (short) 4725, BeepType.XXX, BeepRepetitionType.XXX4));
|
||||
|
||||
// Address for all captures below: 37879811
|
||||
byte[] encoded = new ProgramAlertsCommand(37879811, (short) 3, true, configurations).getEncoded();
|
||||
|
||||
/*
|
||||
Pod expiration alerts
|
||||
assertArrayEquals(Hex.decodeHex("024200038C121910494E532E79A410D1050228001275060280F5"), encoded);
|
||||
}
|
||||
|
||||
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}
|
||||
@Test
|
||||
public void testLowReservoirAlert() throws DecoderException {
|
||||
List<AlertConfiguration> configurations = new ArrayList<>();
|
||||
configurations.add(new AlertConfiguration(AlertSlot.LOW_RESERVOIR, true, (short) 0, false, AlertTriggerType.RESERVOIR_VOLUME_TRIGGER, (short) 200, BeepType.XXX, BeepRepetitionType.XXX));
|
||||
|
||||
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
|
||||
byte[] encoded = new ProgramAlertsCommand(37879811, (short) 8, false, configurations).getEncoded();
|
||||
|
||||
*/
|
||||
assertArrayEquals(Hex.decodeHex("02420003200C190A494E532E4C0000C801020149"), encoded);
|
||||
}
|
||||
|
||||
/*
|
||||
Low reservoir
|
||||
@Test
|
||||
public void testUserExpirationAlert() throws DecoderException {
|
||||
List<AlertConfiguration> configurations = new ArrayList<>();
|
||||
configurations.add(new AlertConfiguration(AlertSlot.USER_POD_EXPIRATION, true, (short) 0, false, AlertTriggerType.TIME_TRIGGER, (short) 4079, BeepType.XXX, BeepRepetitionType.XXX2));
|
||||
|
||||
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}
|
||||
byte[] encoded = new ProgramAlertsCommand(37879811, (short) 15, false, configurations).getEncoded();
|
||||
|
||||
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
|
||||
*/
|
||||
assertArrayEquals(Hex.decodeHex("024200033C0C190A494E532E38000FEF030203E2"), encoded);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Lump of coal
|
||||
@Test
|
||||
public void testLumpOfCoalAlert() throws DecoderException {
|
||||
List<AlertConfiguration> configurations = new ArrayList<>();
|
||||
configurations.add(new AlertConfiguration(AlertSlot.LUMP_OF_COAL_AND_EXPIRATION, true, (short) 55, false, AlertTriggerType.TIME_TRIGGER, (short) 5, BeepType.XXX, BeepRepetitionType.XXX5));
|
||||
|
||||
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}
|
||||
byte[] encoded = new ProgramAlertsCommand(37879811, (short) 10, false, configurations).getEncoded();
|
||||
|
||||
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
|
||||
*/
|
||||
assertArrayEquals(Hex.decodeHex("02420003280C190A494E532E7837000508020356"), encoded);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue