Finished Omnipod Dash program basal command
This commit is contained in:
parent
8d554fa35b
commit
a3b0044874
|
@ -36,12 +36,12 @@ public final class ProgramBasalCommand extends HeaderEnabledCommand {
|
|||
this.delayUntilNextTenthPulseInUsec = delayUntilNextTenthPulseInUsec;
|
||||
}
|
||||
|
||||
public short getLength() {
|
||||
return (short) (insulinProgramElements.size() * 2 + 14);
|
||||
short getLength() {
|
||||
return (short) (insulinProgramElements.size() * 6 + 10);
|
||||
}
|
||||
|
||||
public byte getBodyLength() {
|
||||
return (byte) (insulinProgramElements.size() * 2 + 12);
|
||||
byte getBodyLength() {
|
||||
return (byte) (insulinProgramElements.size() * 6 + 8);
|
||||
}
|
||||
|
||||
@Override public byte[] getEncoded() {
|
||||
|
@ -60,11 +60,11 @@ public final class ProgramBasalCommand extends HeaderEnabledCommand {
|
|||
byte[] interlockCommand = this.interlockCommand.getEncoded();
|
||||
byte[] header = encodeHeader(uniqueId, sequenceNumber, (short) (bolusCommand.length + interlockCommand.length), multiCommandFlag);
|
||||
|
||||
return ByteBuffer.allocate(bolusCommand.length + interlockCommand.length + header.length) //
|
||||
return appendCrc(ByteBuffer.allocate(bolusCommand.length + interlockCommand.length + header.length) //
|
||||
.put(header) //
|
||||
.put(interlockCommand) //
|
||||
.put(bolusCommand) //
|
||||
.array();
|
||||
.array());
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
|
@ -116,12 +116,12 @@ public final class ProgramBasalCommand extends HeaderEnabledCommand {
|
|||
short[] pulsesPerSlot = ProgramBasalUtil.mapBasalProgramToPulsesPerSlot(basalProgram);
|
||||
CurrentSlot currentSlot = ProgramBasalUtil.calculateCurrentSlot(pulsesPerSlot, currentTime);
|
||||
short checksum = ProgramBasalUtil.createChecksum(pulsesPerSlot, currentSlot);
|
||||
List<LongInsulinProgramElement> longInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToLongInsulinProgramElements(pulsesPerSlot);
|
||||
List<LongInsulinProgramElement> longInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToLongInsulinProgramElements(ProgramBasalUtil.mapBasalProgramToTenthPulsesPerSlot(basalProgram));
|
||||
List<ShortInsulinProgramElement> shortInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot);
|
||||
CurrentLongInsulinProgramElement currentLongInsulinProgramElement = ProgramBasalUtil.calculateCurrentLongInsulinProgramElement(longInsulinProgramElements, currentTime);
|
||||
|
||||
ProgramInsulinCommand interlockCommand = new ProgramInsulinCommand(uniqueId, sequenceNumber, multiCommandFlag, nonce,
|
||||
shortInsulinProgramElements, currentSlot.getIndex(), checksum, (short) (currentSlot.getEighthSecondsRemaining() * 8),
|
||||
shortInsulinProgramElements, currentSlot.getIndex(), checksum, currentSlot.getEighthSecondsRemaining(),
|
||||
currentSlot.getPulsesRemaining(), ProgramInsulinCommand.DeliveryType.BASAL);
|
||||
|
||||
return new ProgramBasalCommand(interlockCommand, uniqueId, sequenceNumber, multiCommandFlag,
|
||||
|
|
|
@ -27,12 +27,12 @@ final class ProgramInsulinCommand extends NonceEnabledCommand {
|
|||
this.deliveryType = deliveryType;
|
||||
}
|
||||
|
||||
short getLength() {
|
||||
return (short) (insulinProgramElements.size() * 6 + 10);
|
||||
public short getLength() {
|
||||
return (short) (insulinProgramElements.size() * 2 + 14);
|
||||
}
|
||||
|
||||
byte getBodyLength() {
|
||||
return (byte) (insulinProgramElements.size() * 6 + 8);
|
||||
public byte getBodyLength() {
|
||||
return (byte) (insulinProgramElements.size() * 2 + 12);
|
||||
}
|
||||
|
||||
@Override public byte[] getEncoded() {
|
||||
|
|
|
@ -5,10 +5,10 @@ public enum CommandType {
|
|||
GET_VERSION((byte) 0x07),
|
||||
GET_STATUS((byte) 0x0e),
|
||||
SILENCE_ALERTS((byte) 0x11),
|
||||
PROGRAM_BASAL((byte) 0x13),
|
||||
PROGRAM_BASAL((byte) 0x13), // Always preceded by 0x1a
|
||||
PROGRAM_TEMP_BASAL((byte) 0x16), // Always preceded by 0x1a
|
||||
PROGRAM_BOLUS((byte) 0x17), // Always preceded by 0x1a
|
||||
PROGRAM_ALERTS((byte) 0x19), // Always preceded by 0x1a
|
||||
PROGRAM_ALERTS((byte) 0x19),
|
||||
PROGRAM_INSULIN((byte) 0x1a), // Always followed by one of: 0x13, 0x16, 0x17
|
||||
DEACTIVATE((byte) 0x1c),
|
||||
PROGRAM_BEEPS((byte) 0x1e),
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.insulin.program;
|
||||
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
||||
|
||||
public class CurrentLongInsulinProgramElement implements Encodable {
|
||||
public class CurrentLongInsulinProgramElement {
|
||||
private final byte index;
|
||||
private final int delayUntilNextTenthPulseInUsec;
|
||||
private final short remainingTenthPulses;
|
||||
|
@ -32,8 +30,4 @@ public class CurrentLongInsulinProgramElement implements Encodable {
|
|||
", remainingTenthPulses=" + remainingTenthPulses +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override public byte[] getEncoded() {
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ public final class ProgramBasalUtil {
|
|||
if (i == 0) {
|
||||
previousTenthPulsesPerSlot = tenthPulsesPerSlot[i];
|
||||
numberOfSlotsInCurrentElement = 1;
|
||||
} else if (previousTenthPulsesPerSlot != tenthPulsesPerSlot[i] || numberOfSlotsInCurrentElement >= MAX_NUMBER_OF_SLOTS_IN_INSULIN_PROGRAM_ELEMENT) {
|
||||
elements.add(new LongInsulinProgramElement(startSlotIndex, numberOfSlotsInCurrentElement, (short) (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement), (int) ((NUMBER_OF_USEC_IN_SLOT * numberOfSlotsInCurrentElement) / (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement))));
|
||||
} else if (previousTenthPulsesPerSlot != tenthPulsesPerSlot[i] || (numberOfSlotsInCurrentElement + 1) * previousTenthPulsesPerSlot > 65_534) {
|
||||
elements.add(new LongInsulinProgramElement(startSlotIndex, numberOfSlotsInCurrentElement, (short) (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement), (int) (((long) NUMBER_OF_USEC_IN_SLOT * numberOfSlotsInCurrentElement) / (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement))));
|
||||
|
||||
previousTenthPulsesPerSlot = tenthPulsesPerSlot[i];
|
||||
numberOfSlotsInCurrentElement = 1;
|
||||
|
@ -40,7 +40,7 @@ public final class ProgramBasalUtil {
|
|||
numberOfSlotsInCurrentElement++;
|
||||
}
|
||||
}
|
||||
elements.add(new LongInsulinProgramElement(startSlotIndex, numberOfSlotsInCurrentElement, (short) (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement), (int) ((NUMBER_OF_USEC_IN_SLOT * numberOfSlotsInCurrentElement) / (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement))));
|
||||
elements.add(new LongInsulinProgramElement(startSlotIndex, numberOfSlotsInCurrentElement, (short) (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement), (int) (((long) NUMBER_OF_USEC_IN_SLOT * numberOfSlotsInCurrentElement) / (previousTenthPulsesPerSlot * numberOfSlotsInCurrentElement))));
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ public final class ProgramBasalUtil {
|
|||
|
||||
int durationInSeconds = endTimeInSeconds - startTimeInSeconds;
|
||||
int secondsPassedInCurrentSlot = secondOfDay - startTimeInSeconds;
|
||||
long remainingTenThousandthPulses = (durationInSeconds - secondsPassedInCurrentSlot) * (long) totalNumberOfTenThousandthPulsesInSlot;
|
||||
long remainingTenThousandthPulses = (long) ((durationInSeconds - secondsPassedInCurrentSlot) / (double) durationInSeconds * totalNumberOfTenThousandthPulsesInSlot);
|
||||
int delayBetweenTenthPulsesInUsec = (int) (durationInSeconds * 1_000_000L * 1_000 / totalNumberOfTenThousandthPulsesInSlot);
|
||||
int secondsRemaining = secondsPassedInCurrentSlot % 1_800;
|
||||
int delayUntilNextTenthPulseInUsec = delayBetweenTenthPulsesInUsec;
|
||||
|
@ -215,7 +215,7 @@ public final class ProgramBasalUtil {
|
|||
delayUntilNextTenthPulseInUsec += delayBetweenTenthPulsesInUsec;
|
||||
}
|
||||
}
|
||||
short remainingTenthPulses = (short) ((0 != remainingTenThousandthPulses % 1_000 ? 1 : 0) + remainingTenThousandthPulses / 1_000);
|
||||
short remainingTenthPulses = (short) ((remainingTenThousandthPulses % 1_000 != 0 ? 1 : 0) + remainingTenThousandthPulses / 1_000);
|
||||
|
||||
return new CurrentLongInsulinProgramElement(index, delayUntilNextTenthPulseInUsec, remainingTenthPulses);
|
||||
}
|
||||
|
|
|
@ -5,18 +5,18 @@ import java.nio.ByteBuffer;
|
|||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.Encodable;
|
||||
|
||||
public class ShortInsulinProgramElement implements Encodable {
|
||||
private final byte numberOfSlotsMinusOne; // 4 bits
|
||||
private final byte numberOfSlots; // 4 bits
|
||||
private final short pulsesPerSlot; // 10 bits
|
||||
private final boolean extraAlternatePulse;
|
||||
|
||||
public ShortInsulinProgramElement(byte numberOfSlotsMinusOne, short pulsesPerSlot, boolean extraAlternatePulse) {
|
||||
this.numberOfSlotsMinusOne = numberOfSlotsMinusOne;
|
||||
public ShortInsulinProgramElement(byte numberOfSlots, short pulsesPerSlot, boolean extraAlternatePulse) {
|
||||
this.numberOfSlots = numberOfSlots;
|
||||
this.pulsesPerSlot = pulsesPerSlot;
|
||||
this.extraAlternatePulse = extraAlternatePulse;
|
||||
}
|
||||
|
||||
@Override public byte[] getEncoded() {
|
||||
byte firstByte = (byte) ((((numberOfSlotsMinusOne - 1) & 0x0f) << 4) //
|
||||
byte firstByte = (byte) ((((numberOfSlots - 1) & 0x0f) << 4) //
|
||||
| ((extraAlternatePulse ? 1 : 0) << 3) //
|
||||
| ((pulsesPerSlot >>> 8) & 0x03));
|
||||
|
||||
|
@ -28,7 +28,7 @@ public class ShortInsulinProgramElement implements Encodable {
|
|||
|
||||
@Override public String toString() {
|
||||
return "ShortInsulinProgramElement{" +
|
||||
"numberOfSlotsMinusOne=" + numberOfSlotsMinusOne +
|
||||
"numberOfSlotsMinusOne=" + numberOfSlots +
|
||||
", pulsesPerSlot=" + pulsesPerSlot +
|
||||
", extraAlternatePulse=" + extraAlternatePulse +
|
||||
'}';
|
||||
|
|
|
@ -12,8 +12,8 @@ public class ProgramReminder implements Encodable {
|
|||
}
|
||||
|
||||
@Override public byte[] getEncoded() {
|
||||
return new byte[]{(byte) (((this.atStart ? 0 : 1) << 7)
|
||||
| ((this.atEnd ? 0 : 1) << 6)
|
||||
return new byte[]{(byte) (((this.atStart ? 1 : 0) << 7)
|
||||
| ((this.atEnd ? 1 : 0) << 6)
|
||||
| (this.atInterval & 0x3f))};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
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.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram;
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ProgramReminder;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
public class ProgramBasalCommandTest {
|
||||
@Test
|
||||
public void testProgramBasalCommand() throws DecoderException {
|
||||
List<BasalProgram.Segment> segments = Arrays.asList(
|
||||
new BasalProgram.Segment((short) 0, (short) 48, 300)
|
||||
);
|
||||
BasalProgram basalProgram = new BasalProgram(segments);
|
||||
Date date = new Date(2021, 1, 17, 14, 47, 43);
|
||||
|
||||
byte[] encoded = new ProgramBasalCommand.Builder() //
|
||||
.setUniqueId(37879809) //
|
||||
.setNonce(1229869870) //
|
||||
.setSequenceNumber((short) 10) //
|
||||
.setBasalProgram(basalProgram) //
|
||||
.setCurrentTime(date) //
|
||||
.setProgramReminder(new ProgramReminder(false, true, (byte) 0)) //
|
||||
.build() //
|
||||
.getEncoded();
|
||||
|
||||
System.out.println(Hex.encodeHexString(encoded));
|
||||
assertArrayEquals(Hex.decodeHex("0242000128241A12494E532E0005E81D1708000CF01EF01EF01E130E40001593004C4B403840005B8D80827C"), encoded);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue