Refactoring
This commit is contained in:
parent
d1bf9cefad
commit
34553bbcf6
20 changed files with 336 additions and 256 deletions
omnipod-dash/src
main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod
command
CommandBase.javaDeactivateCommand.javaGetVersionCommand.javaProgramAlertsCommand.javaProgramBasalCommand.javaProgramInsulinCommand.javaSetUniqueIdCommand.javaSilenceAlertsCommand.javaStopDeliveryCommand.java
base
interlock
definition/program
test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command
|
@ -1,117 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.CrcUtil;
|
|
||||||
|
|
||||||
abstract class CommandBase implements Command {
|
|
||||||
static final short HEADER_LENGTH = 6;
|
|
||||||
|
|
||||||
final CommandType commandType;
|
|
||||||
final int address;
|
|
||||||
final short sequenceNumber;
|
|
||||||
final boolean multiCommandFlag;
|
|
||||||
|
|
||||||
CommandBase(CommandType commandType, int address, short sequenceNumber, boolean multiCommandFlag) {
|
|
||||||
this.commandType = commandType;
|
|
||||||
this.address = address;
|
|
||||||
this.sequenceNumber = sequenceNumber;
|
|
||||||
this.multiCommandFlag = multiCommandFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public CommandType getCommandType() {
|
|
||||||
return commandType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAddress() {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getSequenceNumber() {
|
|
||||||
return sequenceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMultiCommandFlag() {
|
|
||||||
return multiCommandFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte[] formatCommand(byte[] command) {
|
|
||||||
List<Byte> temp = new ArrayList<>();
|
|
||||||
|
|
||||||
byte[] prefix = "S0.0=".getBytes(StandardCharsets.UTF_8);
|
|
||||||
for (byte b : prefix) {
|
|
||||||
temp.add(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] length = ByteBuffer.allocate(2).putShort((short) command.length).array();
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
temp.add(length[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append command
|
|
||||||
for (byte b : command) {
|
|
||||||
temp.add(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] suffix = ",G0.0".getBytes(StandardCharsets.UTF_8);
|
|
||||||
for (byte b : suffix) {
|
|
||||||
temp.add(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] out = new byte[((short) temp.size())];
|
|
||||||
for (int i2 = 0; i2 < temp.size(); i2++) {
|
|
||||||
out[i2] = temp.get(i2);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte[] appendCrc(byte[] command) {
|
|
||||||
return ByteBuffer.allocate(command.length + 2) //
|
|
||||||
.put(command) //
|
|
||||||
.putShort(CrcUtil.createCrc(command)) //
|
|
||||||
.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte[] encodeHeader(int address, short sequenceNumber, short length, boolean multiCommandFlag) {
|
|
||||||
return ByteBuffer.allocate(6) //
|
|
||||||
.putInt(address) //
|
|
||||||
.putShort((short) (((sequenceNumber & 0x0f) << 10) | length | ((multiCommandFlag ? 1 : 0) << 15))) //
|
|
||||||
.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
static abstract class Builder<T extends Builder<T, R>, R extends Command> {
|
|
||||||
Integer address;
|
|
||||||
Short sequenceNumber;
|
|
||||||
boolean multiCommandFlag = false;
|
|
||||||
|
|
||||||
public final R build() {
|
|
||||||
if (address == null) {
|
|
||||||
throw new IllegalArgumentException("address can not be null");
|
|
||||||
}
|
|
||||||
if (sequenceNumber == null) {
|
|
||||||
throw new IllegalArgumentException("sequenceNumber can not be null");
|
|
||||||
}
|
|
||||||
return buildCommand();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final T setAddress(int address) {
|
|
||||||
this.address = address;
|
|
||||||
return (T) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final T setSequenceNumber(short sequenceNumber) {
|
|
||||||
this.sequenceNumber = sequenceNumber;
|
|
||||||
return (T) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final T setMultiCommandFlag(boolean multiCommandFlag) {
|
|
||||||
this.multiCommandFlag = multiCommandFlag;
|
|
||||||
return (T) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract R buildCommand();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,12 +2,15 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public final class DeactivateCommand extends CommandBase {
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand;
|
||||||
|
|
||||||
|
public final class DeactivateCommand extends NonceEnabledCommand {
|
||||||
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 DeactivateCommand(int address, short sequenceNumber, boolean multiCommandFlag) {
|
private DeactivateCommand(int address, short sequenceNumber, boolean multiCommandFlag, int nonce) {
|
||||||
super(CommandType.DEACTIVATE, address, sequenceNumber, multiCommandFlag);
|
super(CommandType.DEACTIVATE, address, sequenceNumber, multiCommandFlag, nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public byte[] getEncoded() {
|
@Override public byte[] getEncoded() {
|
||||||
|
@ -15,7 +18,7 @@ public final class DeactivateCommand extends CommandBase {
|
||||||
.put(encodeHeader(address, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(address, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.getValue()) //
|
.put(commandType.getValue()) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.putInt(1229869870) // FIXME ?? was: byte array of int 777211465 converted to little endian
|
.putInt(nonce) //
|
||||||
.array());
|
.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,9 +31,9 @@ public final class DeactivateCommand extends CommandBase {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder extends CommandBase.Builder<Builder, DeactivateCommand> {
|
public static final class Builder extends NonceEnabledBuilder<Builder, DeactivateCommand> {
|
||||||
@Override final DeactivateCommand buildCommand() {
|
@Override protected final DeactivateCommand buildCommand() {
|
||||||
return new DeactivateCommand(address, sequenceNumber, multiCommandFlag);
|
return new DeactivateCommand(Builder.this.address, sequenceNumber, multiCommandFlag, nonce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,10 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public final class GetVersionCommand extends CommandBase {
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand;
|
||||||
|
|
||||||
|
public final class GetVersionCommand extends HeaderEnabledCommand {
|
||||||
public static final int DEFAULT_ADDRESS = -1; // FIXME move
|
public static final int DEFAULT_ADDRESS = -1; // FIXME move
|
||||||
|
|
||||||
private static final short LENGTH = 6;
|
private static final short LENGTH = 6;
|
||||||
|
@ -30,8 +33,8 @@ public final class GetVersionCommand extends CommandBase {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder extends CommandBase.Builder<Builder, GetVersionCommand> {
|
public static final class Builder extends HeaderEnabledBuilder<Builder, GetVersionCommand> {
|
||||||
@Override final GetVersionCommand buildCommand() {
|
@Override protected final GetVersionCommand buildCommand() {
|
||||||
return new GetVersionCommand(address, sequenceNumber, multiCommandFlag);
|
return new GetVersionCommand(address, sequenceNumber, multiCommandFlag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,15 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration;
|
||||||
|
|
||||||
public final class ProgramAlertsCommand extends CommandBase {
|
public final class ProgramAlertsCommand extends NonceEnabledCommand {
|
||||||
private final List<AlertConfiguration> alertConfigurations;
|
private final List<AlertConfiguration> alertConfigurations;
|
||||||
|
|
||||||
private ProgramAlertsCommand(int address, short sequenceNumber, boolean multiCommandFlag, List<AlertConfiguration> alertConfigurations) {
|
private ProgramAlertsCommand(int address, short sequenceNumber, boolean multiCommandFlag, List<AlertConfiguration> alertConfigurations, int nonce) {
|
||||||
super(CommandType.PROGRAM_ALERTS, address, sequenceNumber, multiCommandFlag);
|
super(CommandType.PROGRAM_ALERTS, address, sequenceNumber, multiCommandFlag, nonce);
|
||||||
this.alertConfigurations = new ArrayList<>(alertConfigurations);
|
this.alertConfigurations = new ArrayList<>(alertConfigurations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +21,7 @@ public final class ProgramAlertsCommand extends CommandBase {
|
||||||
.put(encodeHeader(address, sequenceNumber, getLength(), multiCommandFlag)) //
|
.put(encodeHeader(address, sequenceNumber, getLength(), multiCommandFlag)) //
|
||||||
.put(commandType.getValue()) //
|
.put(commandType.getValue()) //
|
||||||
.put(getBodyLength()) //
|
.put(getBodyLength()) //
|
||||||
.putInt(1229869870); // FIXME ?? was: byte array of int 777211465 converted to little endian
|
.putInt(nonce);
|
||||||
for (AlertConfiguration configuration : alertConfigurations) {
|
for (AlertConfiguration configuration : alertConfigurations) {
|
||||||
byteBuffer.put(configuration.getEncoded());
|
byteBuffer.put(configuration.getEncoded());
|
||||||
}
|
}
|
||||||
|
@ -44,7 +46,7 @@ public final class ProgramAlertsCommand extends CommandBase {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder extends CommandBase.Builder<Builder, ProgramAlertsCommand> {
|
public static final class Builder extends NonceEnabledBuilder<Builder, ProgramAlertsCommand> {
|
||||||
private List<AlertConfiguration> alertConfigurations;
|
private List<AlertConfiguration> alertConfigurations;
|
||||||
|
|
||||||
public Builder setAlertConfigurations(List<AlertConfiguration> alertConfigurations) {
|
public Builder setAlertConfigurations(List<AlertConfiguration> alertConfigurations) {
|
||||||
|
@ -52,11 +54,11 @@ public final class ProgramAlertsCommand extends CommandBase {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override final ProgramAlertsCommand buildCommand() {
|
@Override protected final ProgramAlertsCommand buildCommand() {
|
||||||
if (this.alertConfigurations == null) {
|
if (this.alertConfigurations == null) {
|
||||||
throw new IllegalArgumentException("alertConfigurations can not be null");
|
throw new IllegalArgumentException("alertConfigurations can not be null");
|
||||||
}
|
}
|
||||||
return new ProgramAlertsCommand(address, sequenceNumber, multiCommandFlag, alertConfigurations);
|
return new ProgramAlertsCommand(address, sequenceNumber, multiCommandFlag, alertConfigurations, nonce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,102 +4,35 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ProgramReminder;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.program.InsulinProgramElement;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.program.InsulinProgramElement;
|
||||||
|
|
||||||
public final class ProgramBasalCommand extends CommandBase {
|
// Always preceded by 0x1a ProgramInsulinCommand
|
||||||
private final List<InsulinProgramElement> insulinProgramElements;
|
public final class ProgramBasalCommand implements Command {
|
||||||
private final ProgramReminder programReminder;
|
private final List<InsulinProgramElement> uniqueInsulinProgramElements;
|
||||||
private final byte currentHalfOurEntryIndex;
|
|
||||||
private final short remainingPulsesInCurrentHalfHourEntry;
|
|
||||||
private final int delayUntilNextTenthPulseInUsec;
|
|
||||||
|
|
||||||
private ProgramBasalCommand(int address, short sequenceNumber, boolean multiCommandFlag, ProgramReminder programReminder, List<InsulinProgramElement> insulinProgramElements, byte currentHalfOurEntryIndex, short remainingPulsesInCurrentHalfHourEntry, int delayUntilNextTenthPulseInUsec) {
|
private ProgramBasalCommand(List<InsulinProgramElement> uniqueInsulinProgramElements) {
|
||||||
super(CommandType.PROGRAM_BASAL, address, sequenceNumber, multiCommandFlag);
|
this.uniqueInsulinProgramElements = new ArrayList<>(uniqueInsulinProgramElements);
|
||||||
this.insulinProgramElements = new ArrayList<>(insulinProgramElements);
|
}
|
||||||
this.programReminder = programReminder;
|
|
||||||
this.currentHalfOurEntryIndex = currentHalfOurEntryIndex;
|
public short getLength() {
|
||||||
this.remainingPulsesInCurrentHalfHourEntry = remainingPulsesInCurrentHalfHourEntry;
|
return (short) (uniqueInsulinProgramElements.size() * 2 + 14);
|
||||||
this.delayUntilNextTenthPulseInUsec = delayUntilNextTenthPulseInUsec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getBodyLength() {
|
public byte getBodyLength() {
|
||||||
return (byte) (insulinProgramElements.size() * 6 + 8);
|
return (byte) (uniqueInsulinProgramElements.size() * 2 + 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public byte[] getEncoded() {
|
@Override public byte[] getEncoded() {
|
||||||
ByteBuffer basalCommandBuffer = ByteBuffer.allocate(this.getBodyLength()) //
|
return ByteBuffer.allocate(getLength()) //
|
||||||
.put(commandType.getValue()) //
|
// TODO
|
||||||
.put(getBodyLength()) //
|
.array();
|
||||||
.put(programReminder.getEncoded()) //
|
|
||||||
.put(currentHalfOurEntryIndex) //
|
|
||||||
.putShort(remainingPulsesInCurrentHalfHourEntry) //
|
|
||||||
.putInt(delayUntilNextTenthPulseInUsec);
|
|
||||||
|
|
||||||
for (InsulinProgramElement element : insulinProgramElements) {
|
|
||||||
basalCommandBuffer.put(element.getEncoded());
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] basalCommand = basalCommandBuffer.array();
|
|
||||||
|
|
||||||
// TODO basal interlock and header
|
|
||||||
|
|
||||||
return basalCommand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder extends CommandBase.Builder<Builder, ProgramBasalCommand> {
|
@Override public CommandType getCommandType() {
|
||||||
private List<InsulinProgramElement> insulinProgramElements;
|
return CommandType.PROGRAM_BASAL;
|
||||||
private ProgramReminder programReminder;
|
|
||||||
private Byte currentHalfOurEntryIndex;
|
|
||||||
private Short remainingPulsesInCurrentHalfHourEntry;
|
|
||||||
private Integer delayUntilNextTenthPulseInUsec;
|
|
||||||
|
|
||||||
public Builder setInsulinProgramElements(List<InsulinProgramElement> insulinProgramElements) {
|
|
||||||
if (insulinProgramElements == null) {
|
|
||||||
throw new IllegalArgumentException("insulinProgramElements can not be null");
|
|
||||||
}
|
|
||||||
this.insulinProgramElements = new ArrayList<>(insulinProgramElements);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setProgramReminder(ProgramReminder programReminder) {
|
|
||||||
this.programReminder = programReminder;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setCurrentHalfOurEntryIndex(byte currentHalfOurEntryIndex) {
|
|
||||||
this.currentHalfOurEntryIndex = currentHalfOurEntryIndex;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setRemainingPulsesInCurrentHalfHourEntry(short remainingPulsesInCurrentHalfHourEntry) {
|
|
||||||
this.remainingPulsesInCurrentHalfHourEntry = remainingPulsesInCurrentHalfHourEntry;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setDelayUntilNextTenthPulseInUsec(Integer delayUntilNextTenthPulseInUsec) {
|
|
||||||
this.delayUntilNextTenthPulseInUsec = delayUntilNextTenthPulseInUsec;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override final ProgramBasalCommand buildCommand() {
|
|
||||||
if (insulinProgramElements == null) {
|
|
||||||
throw new IllegalArgumentException("insulinProgramElements can not be null");
|
|
||||||
}
|
|
||||||
if (programReminder == null) {
|
|
||||||
throw new IllegalArgumentException("programReminder can not be null");
|
|
||||||
}
|
|
||||||
if (currentHalfOurEntryIndex == null) {
|
|
||||||
throw new IllegalArgumentException("currentHalfOurEntryIndex can not be null");
|
|
||||||
}
|
|
||||||
if (remainingPulsesInCurrentHalfHourEntry == null) {
|
|
||||||
throw new IllegalArgumentException("remainingPulsesInCurrentHalfHourEntry can not be null");
|
|
||||||
}
|
|
||||||
if (delayUntilNextTenthPulseInUsec == null) {
|
|
||||||
throw new IllegalArgumentException("durationUntilNextTenthPulseInUsec can not be null");
|
|
||||||
}
|
|
||||||
return new ProgramBasalCommand(address, sequenceNumber, multiCommandFlag, programReminder, insulinProgramElements, currentHalfOurEntryIndex, remainingPulsesInCurrentHalfHourEntry, delayUntilNextTenthPulseInUsec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO builder
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ProgramReminder;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.program.InsulinProgramElement;
|
||||||
|
|
||||||
|
// Always followed by one of: 0x13, 0x16, 0x17
|
||||||
|
public final class ProgramInsulinCommand extends HeaderEnabledCommand {
|
||||||
|
private final List<InsulinProgramElement> insulinProgramElements;
|
||||||
|
private final ProgramReminder programReminder;
|
||||||
|
private final byte currentHalfOurEntryIndex;
|
||||||
|
private final short remainingPulsesInCurrentHalfHourEntry;
|
||||||
|
private final int delayUntilNextTenthPulseInUsec;
|
||||||
|
private final Command interlockCommand;
|
||||||
|
|
||||||
|
private static final List<CommandType> ALLOWED_INTERLOCK_COMMANDS = Arrays.asList(
|
||||||
|
CommandType.PROGRAM_BASAL,
|
||||||
|
CommandType.PROGRAM_TEMP_BASAL,
|
||||||
|
CommandType.PROGRAM_BOLUS
|
||||||
|
);
|
||||||
|
|
||||||
|
private ProgramInsulinCommand(int address, short sequenceNumber, boolean multiCommandFlag, ProgramReminder programReminder, List<InsulinProgramElement> insulinProgramElements, byte currentHalfOurEntryIndex, short remainingPulsesInCurrentHalfHourEntry, int delayUntilNextTenthPulseInUsec, Command interlockCommand) {
|
||||||
|
super(CommandType.PROGRAM_INSULIN, address, sequenceNumber, multiCommandFlag);
|
||||||
|
this.insulinProgramElements = new ArrayList<>(insulinProgramElements);
|
||||||
|
this.programReminder = programReminder;
|
||||||
|
this.currentHalfOurEntryIndex = currentHalfOurEntryIndex;
|
||||||
|
this.remainingPulsesInCurrentHalfHourEntry = remainingPulsesInCurrentHalfHourEntry;
|
||||||
|
this.delayUntilNextTenthPulseInUsec = delayUntilNextTenthPulseInUsec;
|
||||||
|
this.interlockCommand = interlockCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getLength() {
|
||||||
|
return (short) (insulinProgramElements.size() * 6 + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getBodyLength() {
|
||||||
|
return (byte) (insulinProgramElements.size() * 6 + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public byte[] getEncoded() {
|
||||||
|
ByteBuffer commandBuffer = ByteBuffer.allocate(this.getLength()) //
|
||||||
|
.put(commandType.getValue()) //
|
||||||
|
.put(getBodyLength()) //
|
||||||
|
.put(programReminder.getEncoded()) //
|
||||||
|
.put(currentHalfOurEntryIndex) //
|
||||||
|
.putShort(remainingPulsesInCurrentHalfHourEntry) //
|
||||||
|
.putInt(delayUntilNextTenthPulseInUsec);
|
||||||
|
|
||||||
|
for (InsulinProgramElement element : insulinProgramElements) {
|
||||||
|
commandBuffer.put(element.getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] command = commandBuffer.array();
|
||||||
|
|
||||||
|
// TODO interlock and header
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ProgramBasalBuilder extends HeaderEnabledBuilder<ProgramBasalBuilder, ProgramInsulinCommand> {
|
||||||
|
private List<InsulinProgramElement> insulinProgramElements;
|
||||||
|
private ProgramReminder programReminder;
|
||||||
|
private Byte currentHalfOurEntryIndex;
|
||||||
|
private Short remainingPulsesInCurrentHalfHourEntry;
|
||||||
|
private Integer delayUntilNextTenthPulseInUsec;
|
||||||
|
private Command interlockCommand;
|
||||||
|
|
||||||
|
public ProgramBasalBuilder setInsulinProgramElements(List<InsulinProgramElement> insulinProgramElements) {
|
||||||
|
if (insulinProgramElements == null) {
|
||||||
|
throw new IllegalArgumentException("insulinProgramElements can not be null");
|
||||||
|
}
|
||||||
|
this.insulinProgramElements = new ArrayList<>(insulinProgramElements);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramBasalBuilder setProgramReminder(ProgramReminder programReminder) {
|
||||||
|
this.programReminder = programReminder;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramBasalBuilder setCurrentHalfOurEntryIndex(byte currentHalfOurEntryIndex) {
|
||||||
|
this.currentHalfOurEntryIndex = currentHalfOurEntryIndex;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramBasalBuilder setRemainingPulsesInCurrentHalfHourEntry(short remainingPulsesInCurrentHalfHourEntry) {
|
||||||
|
this.remainingPulsesInCurrentHalfHourEntry = remainingPulsesInCurrentHalfHourEntry;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramBasalBuilder setDelayUntilNextTenthPulseInUsec(Integer delayUntilNextTenthPulseInUsec) {
|
||||||
|
this.delayUntilNextTenthPulseInUsec = delayUntilNextTenthPulseInUsec;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramBasalBuilder setInterlockCommand(Command interlockCommand) {
|
||||||
|
if (!ALLOWED_INTERLOCK_COMMANDS.contains(interlockCommand.getCommandType())) {
|
||||||
|
throw new IllegalArgumentException("Illegal interlock command type");
|
||||||
|
}
|
||||||
|
this.interlockCommand = interlockCommand;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected final ProgramInsulinCommand buildCommand() {
|
||||||
|
if (insulinProgramElements == null) {
|
||||||
|
throw new IllegalArgumentException("insulinProgramElements can not be null");
|
||||||
|
}
|
||||||
|
if (programReminder == null) {
|
||||||
|
throw new IllegalArgumentException("programReminder can not be null");
|
||||||
|
}
|
||||||
|
if (currentHalfOurEntryIndex == null) {
|
||||||
|
throw new IllegalArgumentException("currentHalfOurEntryIndex can not be null");
|
||||||
|
}
|
||||||
|
if (remainingPulsesInCurrentHalfHourEntry == null) {
|
||||||
|
throw new IllegalArgumentException("remainingPulsesInCurrentHalfHourEntry can not be null");
|
||||||
|
}
|
||||||
|
if (delayUntilNextTenthPulseInUsec == null) {
|
||||||
|
throw new IllegalArgumentException("durationUntilNextTenthPulseInUsec can not be null");
|
||||||
|
}
|
||||||
|
if (interlockCommand == null) {
|
||||||
|
throw new IllegalArgumentException("interlockCommand can not be null");
|
||||||
|
}
|
||||||
|
return new ProgramInsulinCommand(address, sequenceNumber, multiCommandFlag, programReminder, insulinProgramElements, currentHalfOurEntryIndex, remainingPulsesInCurrentHalfHourEntry, delayUntilNextTenthPulseInUsec, interlockCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String toString() {
|
||||||
|
return "ProgramInsulinCommand{" +
|
||||||
|
"insulinProgramElements=" + insulinProgramElements +
|
||||||
|
", programReminder=" + programReminder +
|
||||||
|
", currentHalfOurEntryIndex=" + currentHalfOurEntryIndex +
|
||||||
|
", remainingPulsesInCurrentHalfHourEntry=" + remainingPulsesInCurrentHalfHourEntry +
|
||||||
|
", delayUntilNextTenthPulseInUsec=" + delayUntilNextTenthPulseInUsec +
|
||||||
|
", commandType=" + commandType +
|
||||||
|
", address=" + address +
|
||||||
|
", sequenceNumber=" + sequenceNumber +
|
||||||
|
", multiCommandFlag=" + multiCommandFlag +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,10 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public final class SetUniqueIdCommand extends CommandBase {
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand;
|
||||||
|
|
||||||
|
public final class SetUniqueIdCommand extends HeaderEnabledCommand {
|
||||||
private static final int DEFAULT_ADDRESS = -1;
|
private static final int DEFAULT_ADDRESS = -1;
|
||||||
private static final short LENGTH = 21;
|
private static final short LENGTH = 21;
|
||||||
private static final byte BODY_LENGTH = 19;
|
private static final byte BODY_LENGTH = 19;
|
||||||
|
@ -59,7 +62,7 @@ public final class SetUniqueIdCommand extends CommandBase {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder extends CommandBase.Builder<Builder, SetUniqueIdCommand> {
|
public static final class Builder extends HeaderEnabledBuilder<Builder, SetUniqueIdCommand> {
|
||||||
private Integer lotNumber;
|
private Integer lotNumber;
|
||||||
private Integer podSequenceNumber;
|
private Integer podSequenceNumber;
|
||||||
private Date initializationTime;
|
private Date initializationTime;
|
||||||
|
@ -79,7 +82,7 @@ public final class SetUniqueIdCommand extends CommandBase {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override final SetUniqueIdCommand buildCommand() {
|
@Override protected final SetUniqueIdCommand buildCommand() {
|
||||||
if (lotNumber == null) {
|
if (lotNumber == null) {
|
||||||
throw new IllegalArgumentException("lotNumber can not be null");
|
throw new IllegalArgumentException("lotNumber can not be null");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,18 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
||||||
|
|
||||||
public final class SilenceAlertsCommand extends CommandBase {
|
public final class SilenceAlertsCommand extends NonceEnabledCommand {
|
||||||
private static final short LENGTH = (short) 7;
|
private static final short LENGTH = (short) 7;
|
||||||
private static final byte BODY_LENGTH = (byte) 5;
|
private static final byte BODY_LENGTH = (byte) 5;
|
||||||
|
|
||||||
private final SilenceAlertCommandParameters parameters;
|
private final SilenceAlertCommandParameters parameters;
|
||||||
|
|
||||||
private SilenceAlertsCommand(int address, short sequenceNumber, boolean multiCommandFlag, SilenceAlertCommandParameters parameters) {
|
private SilenceAlertsCommand(int address, short sequenceNumber, boolean multiCommandFlag, SilenceAlertCommandParameters parameters, int nonce) {
|
||||||
super(CommandType.SILENCE_ALERTS, address, sequenceNumber, multiCommandFlag);
|
super(CommandType.SILENCE_ALERTS, address, sequenceNumber, multiCommandFlag, nonce);
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ public final class SilenceAlertsCommand extends CommandBase {
|
||||||
.put(encodeHeader(address, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(address, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.getValue()) //
|
.put(commandType.getValue()) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.putInt(1229869870) // FIXME ?? was: byte array of int 777211465 converted to little endian
|
.putInt(nonce) //
|
||||||
.put(parameters.getEncoded()) //
|
.put(parameters.getEncoded()) //
|
||||||
.array());
|
.array());
|
||||||
}
|
}
|
||||||
|
@ -72,7 +74,7 @@ public final class SilenceAlertsCommand extends CommandBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends CommandBase.Builder<Builder, SilenceAlertsCommand> {
|
public static class Builder extends NonceEnabledBuilder<Builder, SilenceAlertsCommand> {
|
||||||
private boolean silenceAutoOffAlert;
|
private boolean silenceAutoOffAlert;
|
||||||
private boolean silenceMultiCommandAlert;
|
private boolean silenceMultiCommandAlert;
|
||||||
private boolean silenceExpirationImminentAlert;
|
private boolean silenceExpirationImminentAlert;
|
||||||
|
@ -122,8 +124,8 @@ public final class SilenceAlertsCommand extends CommandBase {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override SilenceAlertsCommand buildCommand() {
|
@Override protected final SilenceAlertsCommand buildCommand() {
|
||||||
return new SilenceAlertsCommand(address, sequenceNumber, multiCommandFlag, new SilenceAlertCommandParameters(silenceAutoOffAlert, silenceMultiCommandAlert, silenceExpirationImminentAlert, silenceUserSetExpirationAlert, silenceLowReservoirAlert, silenceSuspendInProgressAlert, silenceSuspendEndedAlert, silencePodExpirationAlert));
|
return new SilenceAlertsCommand(address, sequenceNumber, multiCommandFlag, new SilenceAlertCommandParameters(silenceAutoOffAlert, silenceMultiCommandAlert, silenceExpirationImminentAlert, silenceUserSetExpirationAlert, silenceLowReservoirAlert, silenceSuspendInProgressAlert, silenceSuspendEndedAlert, silencePodExpirationAlert), nonce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,21 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.HeaderEnabledCommand;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.NonceEnabledCommand;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
||||||
|
|
||||||
public final class StopDeliveryCommand extends CommandBase {
|
public final class StopDeliveryCommand extends NonceEnabledCommand {
|
||||||
private static final short LENGTH = 7;
|
private static final short LENGTH = 7;
|
||||||
private static final byte BODY_LENGTH = 5;
|
private static final byte BODY_LENGTH = 5;
|
||||||
|
|
||||||
private final DeliveryType deliveryType;
|
private final DeliveryType deliveryType;
|
||||||
private final BeepType beepType;
|
private final BeepType beepType;
|
||||||
|
|
||||||
private StopDeliveryCommand(int address, short sequenceNumber, boolean multiCommandFlag, DeliveryType deliveryType, BeepType beepType) {
|
private StopDeliveryCommand(int address, short sequenceNumber, boolean multiCommandFlag, DeliveryType deliveryType, BeepType beepType, int nonce) {
|
||||||
super(CommandType.STOP_DELIVERY, address, sequenceNumber, multiCommandFlag);
|
super(CommandType.STOP_DELIVERY, address, sequenceNumber, multiCommandFlag, nonce);
|
||||||
this.deliveryType = deliveryType;
|
this.deliveryType = deliveryType;
|
||||||
this.beepType = beepType;
|
this.beepType = beepType;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +27,7 @@ public final class StopDeliveryCommand extends CommandBase {
|
||||||
.put(encodeHeader(address, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(address, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.getValue()) //
|
.put(commandType.getValue()) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.putInt(1229869870) // FIXME ?? was: byte array of int 777211465 converted to little endian
|
.putInt(nonce) //
|
||||||
.put((byte) ((beepType.getValue() << 4) | deliveryType.getEncoded()[0])) //
|
.put((byte) ((beepType.getValue() << 4) | deliveryType.getEncoded()[0])) //
|
||||||
.array());
|
.array());
|
||||||
}
|
}
|
||||||
|
@ -65,7 +68,7 @@ public final class StopDeliveryCommand extends CommandBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder extends CommandBase.Builder<Builder, StopDeliveryCommand> {
|
public static final class Builder extends NonceEnabledBuilder<Builder, StopDeliveryCommand> {
|
||||||
private DeliveryType deliveryType;
|
private DeliveryType deliveryType;
|
||||||
private BeepType beepType = BeepType.LONG_SINGLE_BEEP;
|
private BeepType beepType = BeepType.LONG_SINGLE_BEEP;
|
||||||
|
|
||||||
|
@ -79,14 +82,14 @@ public final class StopDeliveryCommand extends CommandBase {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override final StopDeliveryCommand buildCommand() {
|
@Override protected final StopDeliveryCommand buildCommand() {
|
||||||
if (deliveryType == null) {
|
if (deliveryType == null) {
|
||||||
throw new IllegalArgumentException("deliveryType can not be null");
|
throw new IllegalArgumentException("deliveryType can not be null");
|
||||||
}
|
}
|
||||||
if (beepType == null) {
|
if (beepType == null) {
|
||||||
throw new IllegalArgumentException("beepType can not be null");
|
throw new IllegalArgumentException("beepType can not be null");
|
||||||
}
|
}
|
||||||
return new StopDeliveryCommand(address, sequenceNumber, multiCommandFlag, deliveryType, beepType);
|
return new StopDeliveryCommand(address, sequenceNumber, multiCommandFlag, deliveryType, beepType, nonce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base;
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command;
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base;
|
||||||
|
|
||||||
public enum CommandType {
|
public enum CommandType {
|
||||||
SET_UNIQUE_ID((byte) 0x03),
|
SET_UNIQUE_ID((byte) 0x03),
|
||||||
|
@ -6,10 +6,10 @@ public enum CommandType {
|
||||||
GET_STATUS((byte) 0x0e),
|
GET_STATUS((byte) 0x0e),
|
||||||
SILENCE_ALERTS((byte) 0x11),
|
SILENCE_ALERTS((byte) 0x11),
|
||||||
PROGRAM_BASAL((byte) 0x13),
|
PROGRAM_BASAL((byte) 0x13),
|
||||||
PROGRAM_TEMP_BASAL((byte) 0x16),
|
PROGRAM_TEMP_BASAL((byte) 0x16), // Always preceded by 0x1a
|
||||||
BOLUS((byte) 0x17),
|
PROGRAM_BOLUS((byte) 0x17), // Always preceded by 0x1a
|
||||||
PROGRAM_ALERTS((byte) 0x19),
|
PROGRAM_ALERTS((byte) 0x19), // Always preceded by 0x1a
|
||||||
DELIVERY_INTERLOCK((byte) 0x1a),
|
PROGRAM_INSULIN((byte) 0x1a), // Always followed by one of: 0x13, 0x16, 0x17
|
||||||
DEACTIVATE((byte) 0x1c),
|
DEACTIVATE((byte) 0x1c),
|
||||||
PROGRAM_BEEPS((byte) 0x1e),
|
PROGRAM_BEEPS((byte) 0x1e),
|
||||||
STOP_DELIVERY((byte) 0x1f);
|
STOP_DELIVERY((byte) 0x1f);
|
|
@ -0,0 +1,76 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.CrcUtil;
|
||||||
|
|
||||||
|
public abstract class HeaderEnabledCommand implements Command {
|
||||||
|
protected static final short HEADER_LENGTH = 6;
|
||||||
|
|
||||||
|
protected final CommandType commandType;
|
||||||
|
protected final int address;
|
||||||
|
protected final short sequenceNumber;
|
||||||
|
protected final boolean multiCommandFlag;
|
||||||
|
|
||||||
|
protected HeaderEnabledCommand(CommandType commandType, int address, short sequenceNumber, boolean multiCommandFlag) {
|
||||||
|
this.commandType = commandType;
|
||||||
|
this.address = address;
|
||||||
|
this.sequenceNumber = sequenceNumber;
|
||||||
|
this.multiCommandFlag = multiCommandFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public CommandType getCommandType() {
|
||||||
|
return commandType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte[] appendCrc(byte[] command) {
|
||||||
|
return ByteBuffer.allocate(command.length + 2) //
|
||||||
|
.put(command) //
|
||||||
|
.putShort(CrcUtil.createCrc(command)) //
|
||||||
|
.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte[] encodeHeader(int address, short sequenceNumber, short length, boolean multiCommandFlag) {
|
||||||
|
return ByteBuffer.allocate(6) //
|
||||||
|
.putInt(address) //
|
||||||
|
.putShort((short) (((sequenceNumber & 0x0f) << 10) | length | ((multiCommandFlag ? 1 : 0) << 15))) //
|
||||||
|
.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static abstract class HeaderEnabledBuilder<T extends HeaderEnabledBuilder<T, R>, R extends Command> implements Builder<R> {
|
||||||
|
protected Integer address;
|
||||||
|
protected Short sequenceNumber;
|
||||||
|
protected boolean multiCommandFlag = false;
|
||||||
|
|
||||||
|
public R build() {
|
||||||
|
if (address == null) {
|
||||||
|
throw new IllegalArgumentException("address can not be null");
|
||||||
|
}
|
||||||
|
if (sequenceNumber == null) {
|
||||||
|
throw new IllegalArgumentException("sequenceNumber can not be null");
|
||||||
|
}
|
||||||
|
return buildCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T setAddress(int address) {
|
||||||
|
this.address = address;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T setSequenceNumber(short sequenceNumber) {
|
||||||
|
this.sequenceNumber = sequenceNumber;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T setMultiCommandFlag(boolean multiCommandFlag) {
|
||||||
|
this.multiCommandFlag = multiCommandFlag;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract R buildCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface Builder<R extends Command> {
|
||||||
|
R build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base;
|
||||||
|
|
||||||
|
public abstract class NonceEnabledCommand extends HeaderEnabledCommand {
|
||||||
|
protected final int nonce;
|
||||||
|
|
||||||
|
protected NonceEnabledCommand(CommandType commandType, int address, short sequenceNumber, boolean multiCommandFlag, int nonce) {
|
||||||
|
super(commandType, address, sequenceNumber, multiCommandFlag);
|
||||||
|
this.nonce = nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static abstract class NonceEnabledBuilder<T extends NonceEnabledBuilder<T, R>, R extends Command> extends HeaderEnabledBuilder<T, R> {
|
||||||
|
protected Integer nonce;
|
||||||
|
|
||||||
|
public final R build() {
|
||||||
|
if (nonce == null) {
|
||||||
|
throw new IllegalArgumentException("nonce can not be null");
|
||||||
|
}
|
||||||
|
return super.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T setNonce(int nonce) {
|
||||||
|
this.nonce = nonce;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.interlock;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
|
||||||
|
|
||||||
public class BasalInterlock implements Encodable {
|
|
||||||
@Override public byte[] getEncoded() {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,12 +16,12 @@ public class InsulinProgramElement implements Encodable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public byte[] getEncoded() {
|
@Override public byte[] getEncoded() {
|
||||||
byte firstByte = (byte) ((((numberOfHalfOurEntries - 1) & 0x0f) << 4)
|
byte firstByte = (byte) ((((numberOfHalfOurEntries - 1) & 0x0f) << 4) //
|
||||||
| ((extraAlternatePulse ? 1 : 0) << 3)
|
| ((extraAlternatePulse ? 1 : 0) << 3) //
|
||||||
| ((numberOfPulsesPerHalfOurEntry >>> 8) & 0x03));
|
| ((numberOfPulsesPerHalfOurEntry >>> 8) & 0x03));
|
||||||
|
|
||||||
return ByteBuffer.allocate(2) //
|
return ByteBuffer.allocate(2) //
|
||||||
.put(firstByte)
|
.put(firstByte) //
|
||||||
.put((byte) (numberOfPulsesPerHalfOurEntry & 0xff)) //
|
.put((byte) (numberOfPulsesPerHalfOurEntry & 0xff)) //
|
||||||
.array();
|
.array();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class DeactivateCommandTest {
|
||||||
byte[] encoded = new DeactivateCommand.Builder() //
|
byte[] encoded = new DeactivateCommand.Builder() //
|
||||||
.setAddress(37879809) //
|
.setAddress(37879809) //
|
||||||
.setSequenceNumber((short) 5) //
|
.setSequenceNumber((short) 5) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.build() //
|
.build() //
|
||||||
.getEncoded();
|
.getEncoded();
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class ProgramAlertsCommandTest {
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 3) //
|
.setSequenceNumber((short) 3) //
|
||||||
.setMultiCommandFlag(true) //
|
.setMultiCommandFlag(true) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setAlertConfigurations(configurations) //
|
.setAlertConfigurations(configurations) //
|
||||||
.build() //
|
.build() //
|
||||||
.getEncoded();
|
.getEncoded();
|
||||||
|
@ -41,6 +42,7 @@ public class ProgramAlertsCommandTest {
|
||||||
byte[] encoded = new ProgramAlertsCommand.Builder() //
|
byte[] encoded = new ProgramAlertsCommand.Builder() //
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 8) //
|
.setSequenceNumber((short) 8) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setAlertConfigurations(configurations) //
|
.setAlertConfigurations(configurations) //
|
||||||
.build() //
|
.build() //
|
||||||
.getEncoded();
|
.getEncoded();
|
||||||
|
@ -56,6 +58,7 @@ public class ProgramAlertsCommandTest {
|
||||||
byte[] encoded = new ProgramAlertsCommand.Builder() //
|
byte[] encoded = new ProgramAlertsCommand.Builder() //
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 15) //
|
.setSequenceNumber((short) 15) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setAlertConfigurations(configurations) //
|
.setAlertConfigurations(configurations) //
|
||||||
.build() //
|
.build() //
|
||||||
.getEncoded();
|
.getEncoded();
|
||||||
|
@ -73,6 +76,7 @@ public class ProgramAlertsCommandTest {
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 10) //
|
.setSequenceNumber((short) 10) //
|
||||||
.setMultiCommandFlag(false) //
|
.setMultiCommandFlag(false) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setAlertConfigurations(configurations) //
|
.setAlertConfigurations(configurations) //
|
||||||
.build() //
|
.build() //
|
||||||
.getEncoded();
|
.getEncoded();
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class SetUniqueIdCommandTest {
|
||||||
public void testEncoding() throws DecoderException {
|
public void testEncoding() throws DecoderException {
|
||||||
byte[] encoded = new SetUniqueIdCommand.Builder() //
|
byte[] encoded = new SetUniqueIdCommand.Builder() //
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 6)
|
.setSequenceNumber((short) 6) //
|
||||||
.setLotNumber(135556289) //
|
.setLotNumber(135556289) //
|
||||||
.setPodSequenceNumber(681767) //
|
.setPodSequenceNumber(681767) //
|
||||||
.setInitializationTime(new Date(2021, 1, 10, 14, 41)) //
|
.setInitializationTime(new Date(2021, 1, 10, 14, 41)) //
|
||||||
|
|
|
@ -11,7 +11,8 @@ public class SilenceAlertsCommandTest {
|
||||||
public void testSilenceLowReservoirAlert() throws DecoderException {
|
public void testSilenceLowReservoirAlert() throws DecoderException {
|
||||||
byte[] encoded = new SilenceAlertsCommand.Builder() //
|
byte[] encoded = new SilenceAlertsCommand.Builder() //
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 1)
|
.setSequenceNumber((short) 1) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setSilenceLowReservoirAlert(true) //
|
.setSilenceLowReservoirAlert(true) //
|
||||||
.build() //
|
.build() //
|
||||||
.getEncoded();
|
.getEncoded();
|
||||||
|
|
|
@ -14,6 +14,7 @@ public class StopDeliveryCommandTest {
|
||||||
byte[] encoded = new StopDeliveryCommand.Builder() //
|
byte[] encoded = new StopDeliveryCommand.Builder() //
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 0) //
|
.setSequenceNumber((short) 0) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setDeliveryType(StopDeliveryCommand.DeliveryType.TEMP_BASAL) //
|
.setDeliveryType(StopDeliveryCommand.DeliveryType.TEMP_BASAL) //
|
||||||
.setBeepType(BeepType.LONG_SINGLE_BEEP) //
|
.setBeepType(BeepType.LONG_SINGLE_BEEP) //
|
||||||
.build() //
|
.build() //
|
||||||
|
@ -27,6 +28,7 @@ public class StopDeliveryCommandTest {
|
||||||
byte[] encoded = new StopDeliveryCommand.Builder() //
|
byte[] encoded = new StopDeliveryCommand.Builder() //
|
||||||
.setAddress(37879811) //
|
.setAddress(37879811) //
|
||||||
.setSequenceNumber((short) 2) //
|
.setSequenceNumber((short) 2) //
|
||||||
|
.setNonce(1229869870) //
|
||||||
.setDeliveryType(StopDeliveryCommand.DeliveryType.ALL) //
|
.setDeliveryType(StopDeliveryCommand.DeliveryType.ALL) //
|
||||||
.setBeepType(BeepType.SILENT) //
|
.setBeepType(BeepType.SILENT) //
|
||||||
.build() //
|
.build() //
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue