From a3b0044874c8d670d1fe709c4915023b8221dd69 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Wed, 17 Feb 2021 16:10:18 +0100 Subject: [PATCH] Finished Omnipod Dash program basal command --- .../pod/command/ProgramBasalCommand.java | 16 ++++---- .../pod/command/ProgramInsulinCommand.java | 8 ++-- .../driver/pod/command/base/CommandType.java | 4 +- .../CurrentLongInsulinProgramElement.java | 8 +--- .../insulin/program/ProgramBasalUtil.java | 10 ++--- .../program/ShortInsulinProgramElement.java | 10 ++--- .../pod/definition/ProgramReminder.java | 4 +- .../pod/command/ProgramBasalCommandTest.java | 39 +++++++++++++++++++ 8 files changed, 66 insertions(+), 33 deletions(-) create mode 100644 omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.java diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.java index e111113d81..168ea4d7ea 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommand.java @@ -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 longInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToLongInsulinProgramElements(pulsesPerSlot); + List longInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToLongInsulinProgramElements(ProgramBasalUtil.mapBasalProgramToTenthPulsesPerSlot(basalProgram)); List 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, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.java index 601d8a6122..018bc22f4f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramInsulinCommand.java @@ -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() { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/base/CommandType.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/base/CommandType.java index 7e520d73c5..bd785e573d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/base/CommandType.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/base/CommandType.java @@ -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), diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentLongInsulinProgramElement.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentLongInsulinProgramElement.java index 2c33e8b1bd..5a976a33ee 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentLongInsulinProgramElement.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/CurrentLongInsulinProgramElement.java @@ -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]; - } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ProgramBasalUtil.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ProgramBasalUtil.java index e9197f6c10..35e37f2054 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ProgramBasalUtil.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ProgramBasalUtil.java @@ -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); } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.java index 08768b684e..ab30ccbd85 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/insulin/program/ShortInsulinProgramElement.java @@ -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 + '}'; diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/ProgramReminder.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/ProgramReminder.java index 22b0402e4d..018986eb36 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/ProgramReminder.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/definition/ProgramReminder.java @@ -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))}; } } diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.java b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.java new file mode 100644 index 0000000000..e99e77945d --- /dev/null +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/command/ProgramBasalCommandTest.java @@ -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 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); + } + +} \ No newline at end of file