From 355b833cb2ed157b34a711dcce3d61c9ccd16cb9 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 19 Apr 2020 23:44:56 +0200 Subject: [PATCH 01/15] Rename ConfigurePod* classes to SetupPod* --- .../pump/omnipod/comm/OmnipodManager.java | 4 ++-- ...gurePodAction.java => SetupPodAction.java} | 20 +++++++++---------- ...rePodCommand.java => SetupPodCommand.java} | 6 +++--- ...mandTest.java => SetupPodCommandTest.java} | 6 +++--- 4 files changed, 18 insertions(+), 18 deletions(-) rename app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/{ConfigurePodAction.java => SetupPodAction.java} (75%) rename app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/{ConfigurePodCommand.java => SetupPodCommand.java} (90%) rename app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/{ConfigurePodCommandTest.java => SetupPodCommandTest.java} (79%) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java index 8a461d5b31..4e64ef6092 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java @@ -15,7 +15,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.AcknowledgeAl import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.AssignAddressAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.BolusAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.CancelDeliveryAction; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.ConfigurePodAction; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetupPodAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.DeactivatePodAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.GetPodInfoAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.GetStatusAction; @@ -93,7 +93,7 @@ public class OmnipodManager { } if (SetupProgress.ADDRESS_ASSIGNED.equals(podState.getSetupProgress())) { - communicationService.executeAction(new ConfigurePodAction(podState)); + communicationService.executeAction(new SetupPodAction(podState)); } communicationService.executeAction(new PrimeAction(new PrimeService(), podState)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigurePodAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java similarity index 75% rename from app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigurePodAction.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java index 9ac2ccc74e..2a6135e9ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigurePodAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java @@ -6,7 +6,7 @@ import java.util.Collections; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.ConfigurePodCommand; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetupPodCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; @@ -17,10 +17,10 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPod import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSetupProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; -public class ConfigurePodAction implements OmnipodAction { +public class SetupPodAction implements OmnipodAction { private final PodSessionState podState; - public ConfigurePodAction(PodSessionState podState) { + public SetupPodAction(PodSessionState podState) { this.podState = podState; } @@ -31,13 +31,13 @@ public class ConfigurePodAction implements OmnipodAction { } DateTime activationDate = DateTime.now(podState.getTimeZone()); - ConfigurePodCommand configurePodCommand = new ConfigurePodCommand(podState.getAddress(), activationDate, + SetupPodCommand setupPodCommand = new SetupPodCommand(podState.getAddress(), activationDate, podState.getLot(), podState.getTid()); OmnipodMessage message = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS, - Collections.singletonList(configurePodCommand), podState.getMessageNumber()); - VersionResponse configurePodResponse; + Collections.singletonList(setupPodCommand), podState.getMessageNumber()); + VersionResponse setupPodResponse; try { - configurePodResponse = communicationService.exchangeMessages(VersionResponse.class, podState, + setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podState, message, OmnipodConst.DEFAULT_ADDRESS, podState.getAddress()); } catch (IllegalPacketTypeException ex) { if (PacketType.ACK.equals(ex.getActual())) { @@ -48,12 +48,12 @@ public class ConfigurePodAction implements OmnipodAction { throw ex; } - if (configurePodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_SUCCESS) { - throw new IllegalPodProgressException(PodProgressStatus.PAIRING_SUCCESS, configurePodResponse.getPodProgressStatus()); + if (setupPodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_SUCCESS) { + throw new IllegalPodProgressException(PodProgressStatus.PAIRING_SUCCESS, setupPodResponse.getPodProgressStatus()); } podState.setSetupProgress(SetupProgress.POD_CONFIGURED); - return configurePodResponse; + return setupPodResponse; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/ConfigurePodCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/SetupPodCommand.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/ConfigurePodCommand.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/SetupPodCommand.java index 0f35a1fa24..7ef667d5b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/ConfigurePodCommand.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/SetupPodCommand.java @@ -6,7 +6,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock; import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; -public class ConfigurePodCommand extends MessageBlock { +public class SetupPodCommand extends MessageBlock { private static final byte PACKET_TIMEOUT_LIMIT = 0x04; @@ -15,7 +15,7 @@ public class ConfigurePodCommand extends MessageBlock { private final DateTime date; private final int address; - public ConfigurePodCommand(int address, DateTime date, int lot, int tid) { + public SetupPodCommand(int address, DateTime date, int lot, int tid) { this.address = address; this.lot = lot; this.tid = tid; @@ -46,7 +46,7 @@ public class ConfigurePodCommand extends MessageBlock { @Override public String toString() { - return "ConfigurePodCommand{" + + return "SetupPodCommand{" + "lot=" + lot + ", tid=" + tid + ", date=" + date + diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/ConfigurePodCommandTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/SetupPodCommandTest.java similarity index 79% rename from app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/ConfigurePodCommandTest.java rename to app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/SetupPodCommandTest.java index f553bfbc0a..461b351473 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/ConfigurePodCommandTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/command/SetupPodCommandTest.java @@ -7,10 +7,10 @@ import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import static org.junit.Assert.assertArrayEquals; -public class ConfigurePodCommandTest { +public class SetupPodCommandTest { @Test public void testEncoding() { - ConfigurePodCommand configurePodCommand = new ConfigurePodCommand( // + SetupPodCommand setupPodCommand = new SetupPodCommand( // 0x1f00ee87, // new DateTime(2013, 4, 5, 22, 52, 0), // 41847, // @@ -18,7 +18,7 @@ public class ConfigurePodCommandTest { assertArrayEquals( // ByteUtil.fromHexString("03131f00ee87140404050d16340000a3770003ab37"), // From https://github.com/openaps/openomni/wiki/Command-03-Setup-Pod - configurePodCommand.getRawData()); + setupPodCommand.getRawData()); } // TODO add tests From 9a5cd3c9021916aa590d96e541fb42127056e665 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 26 Apr 2020 21:11:47 +0200 Subject: [PATCH 02/15] Add some checks and logging in Omnipod packet and message exchange --- .../pump/omnipod/OmnipodPumpPlugin.java | 2 - .../comm/OmnipodCommunicationService.java | 64 +++++++++++++------ .../IllegalSequenceNumberException.java | 22 +++++++ .../omnipod/comm/message/OmnipodPacket.java | 12 ++++ .../pump/omnipod/defs/state/PodState.java | 8 +-- .../driver/comm/AapsOmnipodManager.java | 3 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 39b8075e88..cb575a2246 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -971,9 +971,7 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump // Don't trigger an alert when we exceeded the thresholds, but the last communication was successful // This happens when we simply didn't need to send any commands to the pump - return false; } - } return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java index 2fc3a4339a..9ab8693acf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java @@ -15,6 +15,15 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMe import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalResponseException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSequenceNumberException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceOutOfSyncException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceResyncException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NotEnoughDataException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodReturnedErrorResponseException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodPacket; @@ -28,15 +37,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalResponseException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceOutOfSyncException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceResyncException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NotEnoughDataException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodReturnedErrorResponseException; /** * Created by andy on 6/29/18. @@ -153,6 +154,8 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { packetAddress = addressOverride; } + podState.increaseMessageNumber(); + boolean firstPacket = true; byte[] encodedMessage; // this does not work well with the deactivate pod command, we somehow either @@ -207,7 +210,6 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } if (response.getPacketType() == PacketType.ACK) { - podState.increasePacketNumber(1); throw new IllegalPacketTypeException(null, PacketType.ACK); } @@ -216,6 +218,9 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { while (receivedMessage == null) { try { receivedMessage = OmnipodMessage.decodeMessage(receivedMessageData); + if (receivedMessage.getSequenceNumber() != podState.getMessageNumber()) { + throw new IllegalSequenceNumberException(podState.getMessageNumber(), receivedMessage.getSequenceNumber()); + } } catch (NotEnoughDataException ex) { // Message is (probably) not complete yet OmnipodPacket ackForCon = createAckPacket(podState, packetAddress, ackAddressOverride); @@ -235,8 +240,6 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } } - podState.increaseMessageNumber(2); - ackUntilQuiet(podState, packetAddress, ackAddressOverride); List messageBlocks = receivedMessage.getMessageBlocks(); @@ -250,7 +253,13 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } } - return messageBlocks.get(0); + MessageBlock messageBlock = messageBlocks.get(0); + + if (messageBlock.getType() != MessageBlockType.ERROR_RESPONSE) { + podState.increaseMessageNumber(); + } + + return messageBlock; } private OmnipodPacket createAckPacket(PodState podState, Integer packetAddress, Integer messageAddress) { @@ -286,7 +295,7 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex); } - podState.increasePacketNumber(1); + podState.increasePacketNumber(); } private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet) { @@ -300,6 +309,8 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet, int repeatCount, int responseTimeoutMilliseconds, int exchangeTimeoutMilliseconds, int preambleExtensionMilliseconds) { long timeoutTime = System.currentTimeMillis() + exchangeTimeoutMilliseconds; + podState.increasePacketNumber(); + while (System.currentTimeMillis() < timeoutTime) { OmnipodPacket response = null; try { @@ -311,17 +322,34 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } catch (Exception ex) { throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex); } - if (response == null || !response.isValid()) { + if (response == null) { + if (isLoggingEnabled()) { + LOG.debug("exchangePackets response is null"); + } + continue; + } else if (!response.isValid()) { + if (isLoggingEnabled()) { + LOG.debug("exchangePackets response is invalid: " + response); + } continue; } if (response.getAddress() != packet.getAddress()) { - continue; - } - if (response.getSequenceNumber() != ((podState.getPacketNumber() + 1) & 0b11111)) { + if (isLoggingEnabled()) { + LOG.debug("Packet address " + response.getAddress() + " doesn't match " + packet.getAddress()); + } continue; } - podState.increasePacketNumber(2); + if (response.getSequenceNumber() != podState.getPacketNumber()) { + if (isLoggingEnabled()) { + LOG.debug("Packet sequence number " + response.getSequenceNumber() + " does not match " + podState.getPacketNumber()); + } + continue; + } + + // Once we have verification that the POD heard us, we can increment our counters + podState.increasePacketNumber(); + return response; } throw new CommunicationException(CommunicationException.Type.TIMEOUT); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java new file mode 100644 index 0000000000..d47b1e8d0b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception; + +import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; + +public class IllegalSequenceNumberException extends OmnipodException { + private final int expected; + private final int actual; + + public IllegalSequenceNumberException(int expected, int actual) { + super("Invalid sequence number. Expected="+ expected +", actual="+ actual, false); + this.expected = expected; + this.actual = actual; + } + + public int getExpected() { + return expected; + } + + public int getActual() { + return actual; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodPacket.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodPacket.java index fd90ffb640..157e72e51b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodPacket.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodPacket.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.message; +import java.util.Arrays; + import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; @@ -79,4 +81,14 @@ public class OmnipodPacket implements RLMessage { return valid; } + @Override + public String toString() { + return "OmnipodPacket{" + + "packetAddress=" + packetAddress + + ", packetType=" + packetType + + ", sequenceNumber=" + sequenceNumber + + ", encodedMessage=" + ByteUtil.shortHexStringWithoutSpaces(encodedMessage) + + ", valid=" + valid + + '}'; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java index 2e19de1286..c6987c879e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java @@ -46,12 +46,12 @@ public abstract class PodState { this.packetNumber = packetNumber; } - public void increaseMessageNumber(int increment) { - setMessageNumber((messageNumber + increment) & 0b1111); + public void increaseMessageNumber() { + setMessageNumber((messageNumber + 1) & 0b1111); } - public void increasePacketNumber(int increment) { - setPacketNumber((packetNumber + increment) & 0b11111); + public void increasePacketNumber() { + setPacketNumber((packetNumber + 1) & 0b11111); } public boolean hasFaultEvent() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 8399bfdf4b..bbc5345618 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -37,6 +37,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSequenceNumberException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; @@ -612,6 +613,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state); } else if (ex instanceof IllegalResponseException) { comment = getStringResource(R.string.omnipod_driver_error_invalid_response); + } else if (ex instanceof IllegalSequenceNumberException) { + comment = getStringResource(R.string.omnipod_driver_error_invalid_sequence_number); } else if (ex instanceof MessageDecodingException) { comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed); } else if (ex instanceof NonceOutOfSyncException) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2d5da40098..be040f4ac8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1756,6 +1756,7 @@ Communication failed: received an invalid packet from the Pod. Communication failed: the Pod is in a wrong state. Communication failed: received an invalid response from the Pod. + Communication failed: received a message with an invalid sequence number from the Pod. Communication failed: failed to decode message from the Pod. Communication failed: nonce resync failed. Communication failed: nonce out of sync. From ed1efe8944960f4b2d63fbc266b70cc92a534281 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Mon, 27 Apr 2020 22:30:51 +0200 Subject: [PATCH 03/15] Properly decode non-nonce error responses and some renaming/cleanup --- .../comm/OmnipodCommunicationService.java | 5 +-- .../comm/exception/PodFaultException.java | 2 +- .../PodReturnedErrorResponseException.java | 2 +- .../comm/message/response/ErrorResponse.java | 43 +++++++++++++------ .../comm/message/response/StatusResponse.java | 16 +++---- .../message/response/VersionResponse.java | 16 +++---- .../response/podinfo/PodInfoDataLog.java | 12 +++--- .../PodInfoFaultAndInitializationTime.java | 12 +++--- .../response/podinfo/PodInfoFaultEvent.java | 12 +++--- .../pump/omnipod/defs/ErrorResponseType.java | 24 ----------- ...aultEventType.java => FaultEventCode.java} | 10 ++--- .../driver/comm/AapsOmnipodManager.java | 20 ++++----- .../message/response/ErrorResponseTest.java | 18 +++++--- .../response/podinfo/PodInfoDataLogTest.java | 4 +- ...PodInfoFaultAndInitializationTimeTest.java | 4 +- .../podinfo/PodInfoFaultEventTest.java | 12 +++--- 16 files changed, 104 insertions(+), 108 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/ErrorResponseType.java rename app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/{FaultEventType.java => FaultEventCode.java} (95%) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java index 9ab8693acf..7fdf504db2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java @@ -32,7 +32,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.Err import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.ErrorResponseType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; @@ -125,7 +124,7 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } else { if (responseMessageBlock.getType() == MessageBlockType.ERROR_RESPONSE) { ErrorResponse error = (ErrorResponse) responseMessageBlock; - if (error.getErrorResponseType() == ErrorResponseType.BAD_NONCE) { + if (error.getErrorResponseCode() == ErrorResponse.ERROR_RESPONSE_CODE_BAD_NONCE) { podState.resyncNonce(error.getNonceSearchKey(), message.getSentNonce(), message.getSequenceNumber()); if (automaticallyResyncNonce) { message.resyncNonce(podState.getCurrentNonce()); @@ -133,7 +132,7 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { throw new NonceOutOfSyncException(); } } else { - throw new PodReturnedErrorResponseException((ErrorResponse) responseMessageBlock); + throw new PodReturnedErrorResponseException(error); } } else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) { PodInfoFaultEvent faultEvent = ((PodInfoResponse) responseMessageBlock).getPodInfo(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodFaultException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodFaultException.java index 6269f1c39c..7f90a3af36 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodFaultException.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodFaultException.java @@ -7,7 +7,7 @@ public class PodFaultException extends OmnipodException { private final PodInfoFaultEvent faultEvent; public PodFaultException(PodInfoFaultEvent faultEvent) { - super(faultEvent.getFaultEventType().toString(), true); + super(faultEvent.getFaultEventCode().toString(), true); this.faultEvent = faultEvent; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodReturnedErrorResponseException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodReturnedErrorResponseException.java index f43987b755..d552151142 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodReturnedErrorResponseException.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/PodReturnedErrorResponseException.java @@ -7,7 +7,7 @@ public class PodReturnedErrorResponseException extends OmnipodException { private final ErrorResponse errorResponse; public PodReturnedErrorResponseException(ErrorResponse errorResponse) { - super("Pod returned error response: " + errorResponse.getErrorResponseType(), true); + super("Pod returned error response: " + errorResponse, true); this.errorResponse = errorResponse; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponse.java index 18f02475e1..009baaeee4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponse.java @@ -2,14 +2,19 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.ErrorResponseType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; public class ErrorResponse extends MessageBlock { + public static final byte ERROR_RESPONSE_CODE_BAD_NONCE = (byte) 0x14; + private static final int MESSAGE_LENGTH = 5; - private final ErrorResponseType errorResponseType; - private final int nonceSearchKey; + private final byte errorResponseCode; + private Integer nonceSearchKey; // only valid for BAD_NONCE + private FaultEventCode faultEventCode; // valid for all but BAD_NONCE + private PodProgressStatus podProgressStatus; // valid for all but BAD_NONCE public ErrorResponse(byte[] encodedData) { if (encodedData.length < MESSAGE_LENGTH) { @@ -17,14 +22,14 @@ public class ErrorResponse extends MessageBlock { } this.encodedData = ByteUtil.substring(encodedData, 2, MESSAGE_LENGTH - 2); - ErrorResponseType errorResponseType = null; - try { - errorResponseType = ErrorResponseType.fromByte(encodedData[2]); - } catch (IllegalArgumentException ex) { - } + errorResponseCode = encodedData[2]; - this.errorResponseType = errorResponseType; - this.nonceSearchKey = ByteUtil.makeUnsignedShort((int) encodedData[3], (int) encodedData[4]); + if (this.errorResponseCode == ERROR_RESPONSE_CODE_BAD_NONCE) { + nonceSearchKey = ByteUtil.makeUnsignedShort(encodedData[3], encodedData[4]); + } else { + faultEventCode = FaultEventCode.fromByte(encodedData[3]); + podProgressStatus = PodProgressStatus.fromByte(encodedData[4]); + } } @Override @@ -32,19 +37,29 @@ public class ErrorResponse extends MessageBlock { return MessageBlockType.ERROR_RESPONSE; } - public ErrorResponseType getErrorResponseType() { - return errorResponseType; + public byte getErrorResponseCode() { + return errorResponseCode; } - public int getNonceSearchKey() { + public FaultEventCode getFaultEventCode() { + return faultEventCode; + } + + public PodProgressStatus getPodProgressStatus() { + return podProgressStatus; + } + + public Integer getNonceSearchKey() { return nonceSearchKey; } @Override public String toString() { return "ErrorResponse{" + - "errorResponseType=" + errorResponseType + + "errorResponseCode=" + errorResponseCode + ", nonceSearchKey=" + nonceSearchKey + + ", faultEventCode=" + faultEventCode + + ", podProgressStatus=" + podProgressStatus + '}'; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponse.java index a9d831f8ae..ec99632553 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponse.java @@ -31,20 +31,20 @@ public class StatusResponse extends MessageBlock { } this.encodedData = ByteUtil.substring(encodedData, 1, MESSAGE_LENGTH - 1); - this.deliveryStatus = DeliveryStatus.fromByte((byte) (ByteUtil.convertUnsignedByteToInt(encodedData[1]) >>> 4)); - this.podProgressStatus = PodProgressStatus.fromByte((byte) (encodedData[1] & 0x0F)); + deliveryStatus = DeliveryStatus.fromByte((byte) (ByteUtil.convertUnsignedByteToInt(encodedData[1]) >>> 4)); + podProgressStatus = PodProgressStatus.fromByte((byte) (encodedData[1] & 0x0F)); int minutes = ((encodedData[7] & 0x7F) << 6) | ((encodedData[8] & 0xFC) >>> 2); - this.timeActive = Duration.standardMinutes(minutes); + timeActive = Duration.standardMinutes(minutes); int highInsulinBits = (encodedData[2] & 0xF) << 9; int middleInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[3]) << 1; int lowInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[4]) >>> 7; - this.insulinDelivered = OmnipodConst.POD_PULSE_SIZE * (highInsulinBits | middleInsulinBits | lowInsulinBits); - this.podMessageCounter = (byte) ((encodedData[4] >>> 3) & 0xf); + insulinDelivered = OmnipodConst.POD_PULSE_SIZE * (highInsulinBits | middleInsulinBits | lowInsulinBits); + podMessageCounter = (byte) ((encodedData[4] >>> 3) & 0xf); - this.insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * (((encodedData[4] & 0x03) << 8) | ByteUtil.convertUnsignedByteToInt(encodedData[5])); - this.alerts = new AlertSet((byte) (((encodedData[6] & 0x7f) << 1) | (ByteUtil.convertUnsignedByteToInt(encodedData[7]) >>> 7))); + insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * (((encodedData[4] & 0x03) << 8) | ByteUtil.convertUnsignedByteToInt(encodedData[5])); + alerts = new AlertSet((byte) (((encodedData[6] & 0x7f) << 1) | (ByteUtil.convertUnsignedByteToInt(encodedData[7]) >>> 7))); double reservoirValue = (((encodedData[8] & 0x3) << 8) + ByteUtil.convertUnsignedByteToInt(encodedData[9])) * OmnipodConst.POD_PULSE_SIZE; if (reservoirValue > OmnipodConst.MAX_RESERVOIR_READING) { @@ -94,7 +94,7 @@ public class StatusResponse extends MessageBlock { public byte[] getRawData() { ByteArrayOutputStream stream = new ByteArrayOutputStream(); try { - stream.write(this.getType().getValue()); + stream.write(getType().getValue()); stream.write(encodedData); } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java index a8c9e9403d..9b3749d1de 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java @@ -34,18 +34,18 @@ public class VersionResponse extends MessageBlock { throw new IllegalArgumentException("Unrecognized VersionResponse message length: " + length); } - this.podProgressStatus = PodProgressStatus.fromByte(truncatedData[7]); - this.pmVersion = new FirmwareVersion(truncatedData[0], truncatedData[1], truncatedData[2]); - this.piVersion = new FirmwareVersion(truncatedData[3], truncatedData[4], truncatedData[5]); - this.lot = ByteUtil.toInt((int) truncatedData[8], (int) truncatedData[9], + podProgressStatus = PodProgressStatus.fromByte(truncatedData[7]); + pmVersion = new FirmwareVersion(truncatedData[0], truncatedData[1], truncatedData[2]); + piVersion = new FirmwareVersion(truncatedData[3], truncatedData[4], truncatedData[5]); + lot = ByteUtil.toInt((int) truncatedData[8], (int) truncatedData[9], (int) truncatedData[10], (int) truncatedData[11], ByteUtil.BitConversion.BIG_ENDIAN); - this.tid = ByteUtil.toInt((int) truncatedData[12], (int) truncatedData[13], + tid = ByteUtil.toInt((int) truncatedData[12], (int) truncatedData[13], (int) truncatedData[14], (int) truncatedData[15], ByteUtil.BitConversion.BIG_ENDIAN); - int indexIncrementor = extraByte ? 1 : 0; + int indexIncrement = extraByte ? 1 : 0; - this.address = ByteUtil.toInt((int) truncatedData[16 + indexIncrementor], (int) truncatedData[17 + indexIncrementor], - (int) truncatedData[18 + indexIncrementor], (int) truncatedData[19 + indexIncrementor], ByteUtil.BitConversion.BIG_ENDIAN); + address = ByteUtil.toInt((int) truncatedData[16 + indexIncrement], (int) truncatedData[17 + indexIncrement], + (int) truncatedData[18 + indexIncrement], (int) truncatedData[19 + indexIncrement], ByteUtil.BitConversion.BIG_ENDIAN); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLog.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLog.java index a8eebc7696..b8e28169d3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLog.java @@ -7,12 +7,12 @@ import java.util.Collections; import java.util.List; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; public class PodInfoDataLog extends PodInfo { private static final int MINIMUM_MESSAGE_LENGTH = 8; - private final FaultEventType faultEventType; + private final FaultEventCode faultEventCode; private final Duration timeFaultEvent; private final Duration timeSinceActivation; private final byte dataChunkSize; @@ -26,7 +26,7 @@ public class PodInfoDataLog extends PodInfo { throw new IllegalArgumentException("Not enough data"); } - faultEventType = FaultEventType.fromByte(encodedData[1]); + faultEventCode = FaultEventCode.fromByte(encodedData[1]); timeFaultEvent = Duration.standardMinutes(ByteUtil.toInt(encodedData[2], encodedData[3])); timeSinceActivation = Duration.standardMinutes(ByteUtil.toInt(encodedData[4], encodedData[5])); dataChunkSize = encodedData[6]; @@ -45,8 +45,8 @@ public class PodInfoDataLog extends PodInfo { return PodInfoType.DATA_LOG; } - public FaultEventType getFaultEventType() { - return faultEventType; + public FaultEventCode getFaultEventCode() { + return faultEventCode; } public Duration getTimeFaultEvent() { @@ -72,7 +72,7 @@ public class PodInfoDataLog extends PodInfo { @Override public String toString() { return "PodInfoDataLog{" + - "faultEventType=" + faultEventType + + "faultEventCode=" + faultEventCode + ", timeFaultEvent=" + timeFaultEvent + ", timeSinceActivation=" + timeSinceActivation + ", dataChunkSize=" + dataChunkSize + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTime.java index 747b5e821b..2fd1d90406 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTime.java @@ -3,12 +3,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.po import org.joda.time.DateTime; import org.joda.time.Duration; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; public class PodInfoFaultAndInitializationTime extends PodInfo { private static final int MINIMUM_MESSAGE_LENGTH = 17; - private final FaultEventType faultEventType; + private final FaultEventCode faultEventCode; private final Duration timeFaultEvent; private final DateTime initializationTime; @@ -19,7 +19,7 @@ public class PodInfoFaultAndInitializationTime extends PodInfo { throw new IllegalArgumentException("Not enough data"); } - faultEventType = FaultEventType.fromByte(encodedData[1]); + faultEventCode = FaultEventCode.fromByte(encodedData[1]); timeFaultEvent = Duration.standardMinutes(((encodedData[2] & 0b1) << 8) + encodedData[3]); // We ignore time zones here because we don't keep the time zone in which the pod was initially set up // Which is fine because we don't use the initialization time for anything important anyway @@ -31,8 +31,8 @@ public class PodInfoFaultAndInitializationTime extends PodInfo { return PodInfoType.FAULT_AND_INITIALIZATION_TIME; } - public FaultEventType getFaultEventType() { - return faultEventType; + public FaultEventCode getFaultEventCode() { + return faultEventCode; } public Duration getTimeFaultEvent() { @@ -46,7 +46,7 @@ public class PodInfoFaultAndInitializationTime extends PodInfo { @Override public String toString() { return "PodInfoFaultAndInitializationTime{" + - "faultEventType=" + faultEventType + + "faultEventCode=" + faultEventCode + ", timeFaultEvent=" + timeFaultEvent + ", initializationTime=" + initializationTime + '}'; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEvent.java index 9db41a12f7..129ef989bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEvent.java @@ -5,7 +5,7 @@ import org.joda.time.Duration; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet; import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.LogEventErrorCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; @@ -19,7 +19,7 @@ public class PodInfoFaultEvent extends PodInfo { private final double insulinNotDelivered; private final byte podMessageCounter; private final double totalInsulinDelivered; - private final FaultEventType faultEventType; + private final FaultEventCode faultEventCode; private final Duration faultEventTime; private final Double reservoirLevel; private final Duration timeSinceActivation; @@ -44,7 +44,7 @@ public class PodInfoFaultEvent extends PodInfo { insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * ByteUtil.toInt(encodedData[3], encodedData[4]); podMessageCounter = encodedData[5]; totalInsulinDelivered = OmnipodConst.POD_PULSE_SIZE * ByteUtil.toInt(encodedData[6], encodedData[7]); - faultEventType = FaultEventType.fromByte(encodedData[8]); + faultEventCode = FaultEventCode.fromByte(encodedData[8]); int minutesSinceActivation = ByteUtil.toInt(encodedData[9], encodedData[10]); if (minutesSinceActivation == 0xffff) { @@ -99,8 +99,8 @@ public class PodInfoFaultEvent extends PodInfo { return totalInsulinDelivered; } - public FaultEventType getFaultEventType() { - return faultEventType; + public FaultEventCode getFaultEventCode() { + return faultEventCode; } public Duration getFaultEventTime() { @@ -155,7 +155,7 @@ public class PodInfoFaultEvent extends PodInfo { ", insulinNotDelivered=" + insulinNotDelivered + ", podMessageCounter=" + podMessageCounter + ", totalInsulinDelivered=" + totalInsulinDelivered + - ", faultEventType=" + faultEventType + + ", faultEventCode=" + faultEventCode + ", faultEventTime=" + faultEventTime + ", reservoirLevel=" + reservoirLevel + ", timeSinceActivation=" + timeSinceActivation + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/ErrorResponseType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/ErrorResponseType.java deleted file mode 100644 index 883ae94821..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/ErrorResponseType.java +++ /dev/null @@ -1,24 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.defs; - -public enum ErrorResponseType { - BAD_NONCE((byte) 0x14); - - private byte value; - - ErrorResponseType(byte value) { - this.value = value; - } - - public static ErrorResponseType fromByte(byte value) { - for (ErrorResponseType type : values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown ErrorResponseType: " + value); - } - - public byte getValue() { - return value; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/FaultEventType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/FaultEventCode.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/FaultEventType.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/FaultEventCode.java index 69a74aa4c4..df17fd0b5c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/FaultEventType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/FaultEventCode.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.defs; import java.util.Locale; -public enum FaultEventType { +public enum FaultEventCode { NO_FAULTS((byte) 0x00), FAILED_FLASH_ERASE((byte) 0x01), FAILED_FLASH_STORE((byte) 0x02), @@ -124,17 +124,17 @@ public enum FaultEventType { private byte value; - FaultEventType(byte value) { + FaultEventCode(byte value) { this.value = value; } - public static FaultEventType fromByte(byte value) { - for (FaultEventType type : values()) { + public static FaultEventCode fromByte(byte value) { + for (FaultEventCode type : values()) { if (type.value == value) { return type; } } - throw new IllegalArgumentException("Unknown FaultEventType: " + value); + throw new IllegalArgumentException("Unknown FaultEventCode: " + value); } public byte getValue() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index bbc5345618..b1da16fca3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -43,7 +43,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.pod import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType; @@ -330,7 +330,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); if (delegate.getPodState().hasFaultEvent()) { - showPodFaultErrorDialog(delegate.getPodState().getFaultEvent().getFaultEventType(), R.raw.urgentalarm); + showPodFaultErrorDialog(delegate.getPodState().getFaultEvent().getFaultEventCode(), R.raw.urgentalarm); } return new PumpEnactResult().success(true).enacted(true).bolusDelivered(unitsDelivered); @@ -346,7 +346,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface addSuccessToHistory(time, PodHistoryEntryType.CancelBolus, null); return new PumpEnactResult().success(true).enacted(true); } catch (PodFaultException ex) { - showPodFaultErrorDialog(ex.getFaultEvent().getFaultEventType(), null); + showPodFaultErrorDialog(ex.getFaultEvent().getFaultEventCode(), null); addSuccessToHistory(time, PodHistoryEntryType.CancelBolus, null); return new PumpEnactResult().success(true).enacted(true); } catch (Exception ex) { @@ -624,9 +624,9 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface } else if (ex instanceof NotEnoughDataException) { comment = getStringResource(R.string.omnipod_driver_error_not_enough_data); } else if (ex instanceof PodFaultException) { - FaultEventType faultEventType = ((PodFaultException) ex).getFaultEvent().getFaultEventType(); - showPodFaultErrorDialog(faultEventType, R.raw.urgentalarm); - comment = createPodFaultErrorMessage(faultEventType); + FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode(); + showPodFaultErrorDialog(faultEventCode, R.raw.urgentalarm); + comment = createPodFaultErrorMessage(faultEventCode); } else if (ex instanceof PodReturnedErrorResponseException) { comment = getStringResource(R.string.omnipod_driver_error_pod_returned_error_response); } else { @@ -646,10 +646,10 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return comment; } - private String createPodFaultErrorMessage(FaultEventType faultEventType) { + private String createPodFaultErrorMessage(FaultEventCode faultEventCode) { String comment; comment = getStringResource(R.string.omnipod_driver_error_pod_fault, - ByteUtil.convertUnsignedByteToInt(faultEventType.getValue()), faultEventType.name()); + ByteUtil.convertUnsignedByteToInt(faultEventCode.getValue()), faultEventCode.name()); return comment; } @@ -657,8 +657,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface RxBus.INSTANCE.send(event); } - private void showPodFaultErrorDialog(FaultEventType faultEventType, Integer sound) { - showErrorDialog(createPodFaultErrorMessage(faultEventType), sound); + private void showPodFaultErrorDialog(FaultEventCode faultEventCode, Integer sound) { + showErrorDialog(createPodFaultErrorMessage(faultEventCode), sound); } private void showErrorDialog(String message, Integer sound) { diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java index c5556be9f0..84697c0462 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java @@ -3,7 +3,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response; import org.junit.Test; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.ErrorResponseType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -33,14 +34,19 @@ public class ErrorResponseTest { byte[] encodedData = ByteUtil.fromHexString("060314fa92"); ErrorResponse errorResponse = new ErrorResponse(encodedData); - assertEquals(ErrorResponseType.BAD_NONCE, errorResponse.getErrorResponseType()); - // TODO add assertion one nonce search key (obtain captures first) + assertEquals(ErrorResponse.ERROR_RESPONSE_CODE_BAD_NONCE, errorResponse.getErrorResponseCode()); + // TODO add assertion on nonce search key (obtain captures first) + assertNull(errorResponse.getFaultEventCode()); + assertNull(errorResponse.getPodProgressStatus()); } @Test - public void testUnknownError() { - ErrorResponse errorResponse = new ErrorResponse(ByteUtil.fromHexString("060307fa92")); + public void testOtherError() { + ErrorResponse errorResponse = new ErrorResponse(ByteUtil.fromHexString("0603101308")); + assertEquals(0x10, errorResponse.getErrorResponseCode()); + assertEquals(FaultEventCode.MESSAGE_LENGTH_TOO_LONG, errorResponse.getFaultEventCode()); + assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, errorResponse.getPodProgressStatus()); - assertNull(errorResponse.getErrorResponseType()); + assertNull(errorResponse.getNonceSearchKey()); } } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLogTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLogTest.java index 522aec3f48..5db87003bc 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLogTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoDataLogTest.java @@ -4,7 +4,7 @@ import org.joda.time.Duration; import org.junit.Test; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -14,7 +14,7 @@ public class PodInfoDataLogTest { public void testDecoding() { PodInfoDataLog podInfoDataLog = new PodInfoDataLog(ByteUtil.fromHexString("030100010001043c"), 8); // From https://github.com/ps2/rileylink_ios/blob/omnipod-testing/OmniKitTests/PodInfoTests.swift - assertEquals(FaultEventType.FAILED_FLASH_ERASE, podInfoDataLog.getFaultEventType()); + assertEquals(FaultEventCode.FAILED_FLASH_ERASE, podInfoDataLog.getFaultEventCode()); assertTrue(Duration.standardMinutes(1).isEqual(podInfoDataLog.getTimeFaultEvent())); assertTrue(Duration.standardMinutes(1).isEqual(podInfoDataLog.getTimeSinceActivation())); assertEquals(4, podInfoDataLog.getDataChunkSize()); diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTimeTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTimeTest.java index a7288689a3..a7baff4f06 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTimeTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultAndInitializationTimeTest.java @@ -5,7 +5,7 @@ import org.joda.time.Duration; import org.junit.Test; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -15,7 +15,7 @@ public class PodInfoFaultAndInitializationTimeTest { public void testDecoding() { PodInfoFaultAndInitializationTime podInfoFaultAndInitializationTime = new PodInfoFaultAndInitializationTime(ByteUtil.fromHexString("059200010000000000000000091912170e")); // From https://github.com/ps2/rileylink_ios/blob/omnipod-testing/OmniKitTests/PodInfoTests.swift - assertEquals(FaultEventType.BAD_PUMP_REQ_2_STATE, podInfoFaultAndInitializationTime.getFaultEventType()); + assertEquals(FaultEventCode.BAD_PUMP_REQ_2_STATE, podInfoFaultAndInitializationTime.getFaultEventCode()); assertTrue(Duration.standardMinutes(1).isEqual(podInfoFaultAndInitializationTime.getTimeFaultEvent())); DateTime dateTime = podInfoFaultAndInitializationTime.getInitializationTime(); diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java index a15c681ab3..528ac6a9a5 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.LogEventErrorCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; @@ -24,7 +24,7 @@ public class PodInfoFaultEventTest { assertEquals(DeliveryStatus.NORMAL, podInfoFaultEvent.getDeliveryStatus()); assertEquals(0, podInfoFaultEvent.getInsulinNotDelivered(), 0.000001); assertEquals(0x0a, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventType.NO_FAULTS, podInfoFaultEvent.getFaultEventType()); + assertEquals(FaultEventCode.NO_FAULTS, podInfoFaultEvent.getFaultEventCode()); assertTrue(Duration.ZERO.isEqual(podInfoFaultEvent.getFaultEventTime())); assertNull(podInfoFaultEvent.getReservoirLevel()); assertTrue(Duration.standardSeconds(8100).isEqual(podInfoFaultEvent.getTimeSinceActivation())); @@ -44,7 +44,7 @@ public class PodInfoFaultEventTest { assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus()); assertEquals(0, podInfoFaultEvent.getInsulinNotDelivered(), 0.000001); assertEquals(0x09, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventType.PRIME_OPEN_COUNT_TOO_LOW, podInfoFaultEvent.getFaultEventType()); + assertEquals(FaultEventCode.PRIME_OPEN_COUNT_TOO_LOW, podInfoFaultEvent.getFaultEventCode()); assertTrue(Duration.standardSeconds(60).isEqual(podInfoFaultEvent.getFaultEventTime())); assertNull(podInfoFaultEvent.getReservoirLevel()); assertTrue(Duration.standardSeconds(60).isEqual(podInfoFaultEvent.getTimeSinceActivation())); @@ -65,7 +65,7 @@ public class PodInfoFaultEventTest { assertEquals(101.7, podInfoFaultEvent.getTotalInsulinDelivered(), 0.000001); assertEquals(0, podInfoFaultEvent.getInsulinNotDelivered(), 0.000001); assertEquals(0x04, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventType.BASAL_OVER_INFUSION_PULSE, podInfoFaultEvent.getFaultEventType()); + assertEquals(FaultEventCode.BASAL_OVER_INFUSION_PULSE, podInfoFaultEvent.getFaultEventCode()); assertTrue(Duration.standardMinutes(2559).isEqual(podInfoFaultEvent.getFaultEventTime())); assertNull(podInfoFaultEvent.getReservoirLevel()); assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); @@ -85,7 +85,7 @@ public class PodInfoFaultEventTest { assertEquals(11.8, podInfoFaultEvent.getTotalInsulinDelivered(), 0.000001); assertEquals(0.05, podInfoFaultEvent.getInsulinNotDelivered(), 0.000001); assertEquals(0x02, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventType.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventType()); + assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventCode()); assertTrue(Duration.standardMinutes(616).isEqual(podInfoFaultEvent.getFaultEventTime())); assertNull(podInfoFaultEvent.getReservoirLevel()); assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); @@ -105,7 +105,7 @@ public class PodInfoFaultEventTest { assertEquals(11.8, podInfoFaultEvent.getTotalInsulinDelivered(), 0.000001); assertEquals(3276.75, podInfoFaultEvent.getInsulinNotDelivered(), 0.000001); // Insane and will not happen, but this verifies that we convert it to an unsigned int assertEquals(0x02, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventType.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventType()); + assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventCode()); assertTrue(Duration.standardMinutes(616).isEqual(podInfoFaultEvent.getFaultEventTime())); assertNull(podInfoFaultEvent.getReservoirLevel()); assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); From 45ef41d1a3f13314028e48e89557ffb7e26507d8 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Mon, 27 Apr 2020 22:51:44 +0200 Subject: [PATCH 04/15] Accept packets with a packet address of 0xFFFFFFFF to match PDM & Pod --- .../pump/omnipod/comm/OmnipodCommunicationService.java | 8 +++++--- ...on.java => IllegalMessageSequenceNumberException.java} | 6 +++--- .../pump/omnipod/driver/comm/AapsOmnipodManager.java | 6 +++--- app/src/main/res/values/strings.xml | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) rename app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/{IllegalSequenceNumberException.java => IllegalMessageSequenceNumberException.java} (61%) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java index 7fdf504db2..139a3e8dc3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java @@ -18,7 +18,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalResponseException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSequenceNumberException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageSequenceNumberException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceOutOfSyncException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NonceResyncException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.NotEnoughDataException; @@ -37,6 +37,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodState; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; +import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; /** * Created by andy on 6/29/18. @@ -218,7 +219,7 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { try { receivedMessage = OmnipodMessage.decodeMessage(receivedMessageData); if (receivedMessage.getSequenceNumber() != podState.getMessageNumber()) { - throw new IllegalSequenceNumberException(podState.getMessageNumber(), receivedMessage.getSequenceNumber()); + throw new IllegalMessageSequenceNumberException(podState.getMessageNumber(), receivedMessage.getSequenceNumber()); } } catch (NotEnoughDataException ex) { // Message is (probably) not complete yet @@ -332,7 +333,8 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } continue; } - if (response.getAddress() != packet.getAddress()) { + if (response.getAddress() != packet.getAddress() && + response.getAddress() != OmnipodConst.DEFAULT_ADDRESS) { // In some (strange) cases, the Pod remains a packet address of 0xffffffff during it's lifetime if (isLoggingEnabled()) { LOG.debug("Packet address " + response.getAddress() + " doesn't match " + packet.getAddress()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageSequenceNumberException.java similarity index 61% rename from app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageSequenceNumberException.java index d47b1e8d0b..b26d2b6ff8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalSequenceNumberException.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageSequenceNumberException.java @@ -2,12 +2,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; -public class IllegalSequenceNumberException extends OmnipodException { +public class IllegalMessageSequenceNumberException extends OmnipodException { private final int expected; private final int actual; - public IllegalSequenceNumberException(int expected, int actual) { - super("Invalid sequence number. Expected="+ expected +", actual="+ actual, false); + public IllegalMessageSequenceNumberException(int expected, int actual) { + super("Invalid message sequence number. Expected="+ expected +", actual="+ actual, false); this.expected = expected; this.actual = actual; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index b1da16fca3..40b3454f71 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -37,7 +37,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSequenceNumberException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageSequenceNumberException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; @@ -613,8 +613,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state); } else if (ex instanceof IllegalResponseException) { comment = getStringResource(R.string.omnipod_driver_error_invalid_response); - } else if (ex instanceof IllegalSequenceNumberException) { - comment = getStringResource(R.string.omnipod_driver_error_invalid_sequence_number); + } else if (ex instanceof IllegalMessageSequenceNumberException) { + comment = getStringResource(R.string.omnipod_driver_error_invalid_message_sequence_number); } else if (ex instanceof MessageDecodingException) { comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed); } else if (ex instanceof NonceOutOfSyncException) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index be040f4ac8..a97887f5f8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1756,7 +1756,7 @@ Communication failed: received an invalid packet from the Pod. Communication failed: the Pod is in a wrong state. Communication failed: received an invalid response from the Pod. - Communication failed: received a message with an invalid sequence number from the Pod. + Communication failed: received a message with an invalid sequence number from the Pod. Communication failed: failed to decode message from the Pod. Communication failed: nonce resync failed. Communication failed: nonce out of sync. From b8f2fdc7a889afa9db19c3f639f534c3d080ec18 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Mon, 27 Apr 2020 22:55:31 +0200 Subject: [PATCH 05/15] Small cleanup --- .../omnipod/comm/OmnipodCommunicationService.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java index 139a3e8dc3..8c29a1356c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java @@ -263,15 +263,13 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } private OmnipodPacket createAckPacket(PodState podState, Integer packetAddress, Integer messageAddress) { - int pktAddress = podState.getAddress(); - int msgAddress = podState.getAddress(); - if (packetAddress != null) { - pktAddress = packetAddress; + if(packetAddress == null) { + packetAddress = podState.getAddress(); } - if (messageAddress != null) { - msgAddress = messageAddress; + if(messageAddress == null) { + messageAddress = podState.getAddress(); } - return new OmnipodPacket(pktAddress, PacketType.ACK, podState.getPacketNumber(), ByteUtil.getBytesFromInt(msgAddress)); + return new OmnipodPacket(packetAddress, PacketType.ACK, podState.getPacketNumber(), ByteUtil.getBytesFromInt(messageAddress)); } private void ackUntilQuiet(PodState podState, Integer packetAddress, Integer messageAddress) { From 5d25e39dd1678c970f2bda942b5e21747fa31b39 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Mon, 27 Apr 2020 23:14:00 +0200 Subject: [PATCH 06/15] Verify the message address before accepting --- .../comm/OmnipodCommunicationService.java | 4 ++++ .../IllegalMessageAddressException.java | 22 +++++++++++++++++++ .../omnipod/comm/message/OmnipodMessage.java | 5 ++++- .../driver/comm/AapsOmnipodManager.java | 3 +++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageAddressException.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java index 8c29a1356c..d610c43ddb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java @@ -16,6 +16,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.Rile import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalResponseException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageSequenceNumberException; @@ -218,6 +219,9 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { while (receivedMessage == null) { try { receivedMessage = OmnipodMessage.decodeMessage(receivedMessageData); + if(receivedMessage.getAddress() != message.getAddress()) { + throw new IllegalMessageAddressException(message.getAddress(), receivedMessage.getAddress()); + } if (receivedMessage.getSequenceNumber() != podState.getMessageNumber()) { throw new IllegalMessageSequenceNumberException(podState.getMessageNumber(), receivedMessage.getSequenceNumber()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageAddressException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageAddressException.java new file mode 100644 index 0000000000..9c674cd8ca --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalMessageAddressException.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception; + +import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; + +public class IllegalMessageAddressException extends OmnipodException { + private final int expected; + private final int actual; + + public IllegalMessageAddressException(int expected, int actual) { + super("Invalid message address. Expected="+ expected +", actual="+ actual, false); + this.expected = expected; + this.actual = actual; + } + + public int getExpected() { + return expected; + } + + public int getActual() { + return actual; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodMessage.java index c328997172..78cfa72e19 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodMessage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/OmnipodMessage.java @@ -97,6 +97,10 @@ public class OmnipodMessage { } } + public int getAddress() { + return address; + } + public List getMessageBlocks() { return messageBlocks; } @@ -135,7 +139,6 @@ public class OmnipodMessage { return false; } - @Override public String toString() { return "OmnipodMessage{" + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 40b3454f71..34fdce45e0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -37,6 +37,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageSequenceNumberException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog; @@ -615,6 +616,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface comment = getStringResource(R.string.omnipod_driver_error_invalid_response); } else if (ex instanceof IllegalMessageSequenceNumberException) { comment = getStringResource(R.string.omnipod_driver_error_invalid_message_sequence_number); + } else if (ex instanceof IllegalMessageAddressException) { + comment = getStringResource(R.string.omnipod_driver_error_invalid_message_address); } else if (ex instanceof MessageDecodingException) { comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed); } else if (ex instanceof NonceOutOfSyncException) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a97887f5f8..b112907813 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1757,6 +1757,7 @@ Communication failed: the Pod is in a wrong state. Communication failed: received an invalid response from the Pod. Communication failed: received a message with an invalid sequence number from the Pod. + Communication failed: received a message with an invalid address from the Pod. Communication failed: failed to decode message from the Pod. Communication failed: nonce resync failed. Communication failed: nonce out of sync. From b515fbae927bd8aa5ff0c2ac7bc3c410da442fcf Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Tue, 28 Apr 2020 23:11:32 +0200 Subject: [PATCH 07/15] Update VersionResponse --- .../message/response/VersionResponse.java | 72 ++++++++++++------- .../message/response/VersionResponseTest.java | 24 +++++-- 2 files changed, 65 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java index 9b3749d1de..c62add6732 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponse.java @@ -7,45 +7,51 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; public class VersionResponse extends MessageBlock { + private static final int ASSIGN_ADDRESS_VERSION_RESPONSE_LENGTH = 0x15; + private static final int SETUP_POD_VERSION_RESPONSE_LENGTH = 0x1b; + private final PodProgressStatus podProgressStatus; private final FirmwareVersion pmVersion; private final FirmwareVersion piVersion; private final int lot; private final int tid; + private Byte gain; // Only in the assign address version response + private Byte rssi; // Only in the assign address version response private final int address; - public VersionResponse(byte[] encodedData) { - int length = ByteUtil.convertUnsignedByteToInt(encodedData[1]) + 2; - this.encodedData = ByteUtil.substring(encodedData, 2, length - 2); - - boolean extraByte; - byte[] truncatedData; + public VersionResponse(byte[] data) { + int length = ByteUtil.convertUnsignedByteToInt(data[1]); + this.encodedData = ByteUtil.substring(data, 2, length); switch (length) { - case 0x17: - truncatedData = ByteUtil.substring(encodedData, 2); - extraByte = true; + case ASSIGN_ADDRESS_VERSION_RESPONSE_LENGTH: + podProgressStatus = PodProgressStatus.fromByte(data[9]); + pmVersion = new FirmwareVersion(data[2], data[3], data[4]); + piVersion = new FirmwareVersion(data[5], data[6], data[7]); + lot = ByteUtil.toInt((int) data[10], (int) data[11], + (int) data[12], (int) data[13], ByteUtil.BitConversion.BIG_ENDIAN); + tid = ByteUtil.toInt((int) data[14], (int) data[15], + (int) data[16], (int) data[17], ByteUtil.BitConversion.BIG_ENDIAN); + gain = (byte) ((data[18] & 0xc0) >>> 6); + rssi = (byte) (data[18] & 0x3f); + address = ByteUtil.toInt((int) data[19], (int) data[20], + (int) data[21], (int) data[22], ByteUtil.BitConversion.BIG_ENDIAN); break; - case 0x1D: - truncatedData = ByteUtil.substring(encodedData, 9); - extraByte = false; + case SETUP_POD_VERSION_RESPONSE_LENGTH: + podProgressStatus = PodProgressStatus.fromByte(data[16]); + pmVersion = new FirmwareVersion(data[9], data[10], data[11]); + piVersion = new FirmwareVersion(data[12], data[13], data[14]); + lot = ByteUtil.toInt((int) data[17], (int) data[18], + (int) data[19], (int) data[20], ByteUtil.BitConversion.BIG_ENDIAN); + tid = ByteUtil.toInt((int) data[21], (int) data[22], + (int) data[23], (int) data[24], ByteUtil.BitConversion.BIG_ENDIAN); + + address = ByteUtil.toInt((int) data[25], (int) data[26], + (int) data[27], (int) data[28], ByteUtil.BitConversion.BIG_ENDIAN); break; default: throw new IllegalArgumentException("Unrecognized VersionResponse message length: " + length); } - - podProgressStatus = PodProgressStatus.fromByte(truncatedData[7]); - pmVersion = new FirmwareVersion(truncatedData[0], truncatedData[1], truncatedData[2]); - piVersion = new FirmwareVersion(truncatedData[3], truncatedData[4], truncatedData[5]); - lot = ByteUtil.toInt((int) truncatedData[8], (int) truncatedData[9], - (int) truncatedData[10], (int) truncatedData[11], ByteUtil.BitConversion.BIG_ENDIAN); - tid = ByteUtil.toInt((int) truncatedData[12], (int) truncatedData[13], - (int) truncatedData[14], (int) truncatedData[15], ByteUtil.BitConversion.BIG_ENDIAN); - - int indexIncrement = extraByte ? 1 : 0; - - address = ByteUtil.toInt((int) truncatedData[16 + indexIncrement], (int) truncatedData[17 + indexIncrement], - (int) truncatedData[18 + indexIncrement], (int) truncatedData[19 + indexIncrement], ByteUtil.BitConversion.BIG_ENDIAN); } @Override @@ -73,6 +79,22 @@ public class VersionResponse extends MessageBlock { return tid; } + public Byte getGain() { + return gain; + } + + public Byte getRssi() { + return rssi; + } + + public boolean isAssignAddressVersionResponse() { + return encodedData.length == ASSIGN_ADDRESS_VERSION_RESPONSE_LENGTH; + } + + public boolean isSetupPodVersionResponse() { + return encodedData.length == SETUP_POD_VERSION_RESPONSE_LENGTH; + } + public int getAddress() { return address; } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java index 62afe4f090..891ad81329 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java @@ -7,10 +7,14 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; public class VersionResponseTest { @Test - public void testRawDataShortResponse() { + public void testRawDataAssignAddressVersionResponse() { byte[] encodedData = ByteUtil.fromHexString("011502070002070002020000a64000097c279c1f08ced2"); VersionResponse versionResponse = new VersionResponse(encodedData); @@ -18,7 +22,7 @@ public class VersionResponseTest { } @Test - public void testRawDataShortResponseWithLongerMessage() { + public void testRawDataAssignAddressVersionResponseWithLongerMessage() { byte[] encodedData = ByteUtil.fromHexString("011502070002070002020000a64000097c279c1f08ced201"); byte[] expected = ByteUtil.fromHexString("011502070002070002020000a64000097c279c1f08ced2"); @@ -27,7 +31,7 @@ public class VersionResponseTest { } @Test - public void testRawDataLongResponse() { + public void testRawDataSetupPodVersionResponse() { byte[] encodedData = ByteUtil.fromHexString("011b13881008340a5002070002070002030000a3770003ab371f00ee87"); VersionResponse versionResponse = new VersionResponse(encodedData); @@ -36,7 +40,7 @@ public class VersionResponseTest { } @Test - public void testRawDataLongResponseWithLongerMessage() { + public void testRawDataSetupPodVersionResponseWithLongerMessage() { byte[] encodedData = ByteUtil.fromHexString("011b13881008340a5002070002070002030000a3770003ab371f00ee8701"); byte[] expected = ByteUtil.fromHexString("011b13881008340a5002070002070002030000a3770003ab371f00ee87"); @@ -45,25 +49,33 @@ public class VersionResponseTest { } @Test - public void testVersionResponse() { + public void testAssignAddressVersionResponse() { VersionResponse versionResponse = new VersionResponse(ByteUtil.fromHexString("011502070002070002020000a64000097c279c1f08ced2")); + assertTrue(versionResponse.isAssignAddressVersionResponse()); + assertFalse(versionResponse.isSetupPodVersionResponse()); assertEquals(0x1f08ced2, versionResponse.getAddress()); assertEquals(42560, versionResponse.getLot()); assertEquals(621607, versionResponse.getTid()); assertEquals("2.7.0", versionResponse.getPiVersion().toString()); assertEquals("2.7.0", versionResponse.getPmVersion().toString()); + assertNotNull(versionResponse.getRssi()); + assertNotNull(versionResponse.getGain()); } @Test - public void testLongVersionResponse() { + public void testSetupPodVersionResponse() { VersionResponse versionResponse = new VersionResponse(ByteUtil.fromHexString("011b13881008340a5002070002070002030000a3770003ab371f00ee87")); + assertFalse(versionResponse.isAssignAddressVersionResponse()); + assertTrue(versionResponse.isSetupPodVersionResponse()); assertEquals(0x1f00ee87, versionResponse.getAddress()); assertEquals(41847, versionResponse.getLot()); assertEquals(240439, versionResponse.getTid()); assertEquals(PodProgressStatus.PAIRING_SUCCESS, versionResponse.getPodProgressStatus()); assertEquals("2.7.0", versionResponse.getPiVersion().toString()); assertEquals("2.7.0", versionResponse.getPmVersion().toString()); + assertNull(versionResponse.getRssi()); + assertNull(versionResponse.getGain()); } } From b482f0690f392d491ef96d869f08cc24a5f68af0 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Wed, 29 Apr 2020 00:01:11 +0200 Subject: [PATCH 08/15] WIP on always retrying 0x07 and 0x03 messages together --- .../pump/omnipod/comm/OmnipodManager.java | 19 ++++++++++++------- .../comm/action/AssignAddressAction.java | 17 +++++++++++------ .../omnipod/comm/action/SetupPodAction.java | 8 ++++++++ .../IllegalVersionResponseTypeException.java | 9 +++++++++ .../driver/comm/AapsOmnipodManager.java | 5 ++++- 5 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalVersionResponseTypeException.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java index 4e64ef6092..0c30d2f6c4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java @@ -7,6 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.EnumSet; +import java.util.Random; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -81,19 +82,18 @@ public class OmnipodManager { this(communicationService, podState, null); } - public synchronized Single pairAndPrime() { + public synchronized Single pairAndPrime(int address) { logStartingCommandExecution("pairAndPrime"); try { - if (podState == null) { + if (podState == null || podState.getSetupProgress().isBefore(SetupProgress.POD_CONFIGURED)) { + // Always send both 0x07 and 0x03 on retries podState = communicationService.executeAction( - new AssignAddressAction(podStateChangedHandler)); - } else if (SetupProgress.PRIMING.isBefore(podState.getSetupProgress())) { - throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, podState.getSetupProgress()); - } + new AssignAddressAction(podStateChangedHandler, address)); - if (SetupProgress.ADDRESS_ASSIGNED.equals(podState.getSetupProgress())) { communicationService.executeAction(new SetupPodAction(podState)); + } else if (SetupProgress.PRIMING.isBefore(podState.getSetupProgress())) { + throw new IllegalSetupProgressException(SetupProgress.POD_CONFIGURED, podState.getSetupProgress()); } communicationService.executeAction(new PrimeAction(new PrimeService(), podState)); @@ -592,6 +592,11 @@ public class OmnipodManager { return ex instanceof OmnipodException && ((OmnipodException) ex).isCertainFailure(); } + public static int generateRandomAddress() { + // Create random address with 20 bits to match PDM, could easily use 24 bits instead + return 0x1f000000 | (new Random().nextInt() & 0x000fffff); + } + public static class BolusCommandResult { private final CommandDeliveryStatus commandDeliveryStatus; private final SingleSubject deliveryResultSubject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java index 09b096f78d..01a6180027 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java @@ -6,6 +6,8 @@ import java.util.Collections; import java.util.Random; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.AssignAddressCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse; @@ -18,15 +20,11 @@ public class AssignAddressAction implements OmnipodAction { private final int address; private final PodStateChangedHandler podStateChangedHandler; - public AssignAddressAction(PodStateChangedHandler podStateChangedHandler) { - this.address = generateRandomAddress(); + public AssignAddressAction(PodStateChangedHandler podStateChangedHandler, int address) { + this.address = address; this.podStateChangedHandler = podStateChangedHandler; } - private static int generateRandomAddress() { - return 0x1f000000 | (new Random().nextInt() & 0x000fffff); - } - @Override public PodSessionState execute(OmnipodCommunicationService communicationService) { PodSetupState setupState = new PodSetupState(address, 0x00, 0x00); @@ -38,6 +36,13 @@ public class AssignAddressAction implements OmnipodAction { VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, setupState, assignAddressMessage, OmnipodConst.DEFAULT_ADDRESS, setupState.getAddress()); + if(!assignAddressResponse.isAssignAddressVersionResponse()) { + throw new IllegalVersionResponseTypeException("assignAddress", "setupPod"); + } + if(assignAddressResponse.getAddress() != address) { + throw new IllegalMessageAddressException(address, assignAddressResponse.getAddress()); + } + DateTimeZone timeZone = DateTimeZone.getDefault(); PodSessionState podState = new PodSessionState(timeZone, address, assignAddressResponse.getPiVersion(), diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java index 2a6135e9ab..b6c81196c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java @@ -5,6 +5,8 @@ import org.joda.time.DateTime; import java.util.Collections; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetupPodCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse; @@ -48,6 +50,12 @@ public class SetupPodAction implements OmnipodAction { throw ex; } + if(!setupPodResponse.isSetupPodVersionResponse()) { + throw new IllegalVersionResponseTypeException("setupPod", "assignAddress"); + } + if(setupPodResponse.getAddress() != podState.getAddress()) { + throw new IllegalMessageAddressException(podState.getAddress(), setupPodResponse.getAddress()); + } if (setupPodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_SUCCESS) { throw new IllegalPodProgressException(PodProgressStatus.PAIRING_SUCCESS, setupPodResponse.getPodProgressStatus()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalVersionResponseTypeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalVersionResponseTypeException.java new file mode 100644 index 0000000000..0dbe0805d5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/exception/IllegalVersionResponseTypeException.java @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.comm.exception; + +import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; + +public class IllegalVersionResponseTypeException extends OmnipodException { + public IllegalVersionResponseTypeException(String expected, String actual) { + super("Invalid Version Response type. Expected="+ expected +", actual="+ actual, false); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 34fdce45e0..f8ca563156 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -170,7 +170,10 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface long time = System.currentTimeMillis(); if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) { try { - Disposable disposable = delegate.pairAndPrime().subscribe(res -> // + // BS FIXME use static address for retries + int address = OmnipodManager.generateRandomAddress(); + + Disposable disposable = delegate.pairAndPrime(address).subscribe(res -> // handleSetupActionResult(podInitActionType, podInitReceiver, res, time, null)); return new PumpEnactResult().success(true).enacted(true); } catch (Exception ex) { From a0e5ec74faa1ce00219e6d93b000ad7f09f65be1 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Wed, 29 Apr 2020 00:10:53 +0200 Subject: [PATCH 09/15] Improve exception handling --- .../pump/omnipod/driver/comm/AapsOmnipodManager.java | 9 ++++++++- app/src/main/res/values/strings.xml | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index f8ca563156..354ffc3f48 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -39,6 +39,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageSequenceNumberException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; @@ -607,7 +608,11 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface if (ex instanceof ActionInitializationException || ex instanceof CommandInitializationException) { comment = getStringResource(R.string.omnipod_driver_error_invalid_parameters); } else if (ex instanceof CommunicationException) { - comment = getStringResource(R.string.omnipod_driver_error_communication_failed); + if(((CommunicationException) ex).getType() == CommunicationException.Type.TIMEOUT) { + comment = getStringResource(R.string.omnipod_driver_error_communication_failed_timeout); + } else { + comment = getStringResource(R.string.omnipod_driver_error_communication_failed_unexpected_exception); + } } else if (ex instanceof CrcMismatchException) { comment = getStringResource(R.string.omnipod_driver_error_crc_mismatch); } else if (ex instanceof IllegalPacketTypeException) { @@ -615,6 +620,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface } else if (ex instanceof IllegalPodProgressException || ex instanceof IllegalSetupProgressException || ex instanceof IllegalDeliveryStatusException) { comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state); + } else if (ex instanceof IllegalVersionResponseTypeException) { + comment = getStringResource(R.string.omnipod_driver_error_invalid_response); } else if (ex instanceof IllegalResponseException) { comment = getStringResource(R.string.omnipod_driver_error_invalid_response); } else if (ex instanceof IllegalMessageSequenceNumberException) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b112907813..0a6d531f62 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1749,9 +1749,10 @@ No active pod. Command verification failed. - An unexpected error occured. Please report! (type: %1$s). + An unexpected error occurred. Please report! (type: %1$s). Communication failed: received invalid input parameters. - Communication failed. + Communication failed: timeout. + Communication failed: an unexpected error occurred. Please report! Communication failed: message integrity verification failed. Communication failed: received an invalid packet from the Pod. Communication failed: the Pod is in a wrong state. From a0b4e0c7ce17c610c149a2bdff5e9c95d92bebb0 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 3 May 2020 12:59:24 +0200 Subject: [PATCH 10/15] Update PodProgressStatus values to match Omnikit Wiki --- .../pump/omnipod/comm/action/PrimeAction.java | 2 +- .../omnipod/comm/action/SetupPodAction.java | 4 +-- .../pump/omnipod/defs/PodProgressStatus.java | 32 +++++++++---------- .../message/response/ErrorResponseTest.java | 2 +- .../message/response/StatusResponseTest.java | 6 ++-- .../message/response/VersionResponseTest.java | 2 +- .../podinfo/PodInfoFaultEventTest.java | 10 +++--- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java index 65d250e399..9dc154134e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java @@ -30,7 +30,7 @@ public class PrimeAction implements OmnipodAction { } public static void updatePrimingStatus(PodSessionState podState, StatusResponse statusResponse) { - if (podState.getSetupProgress().equals(SetupProgress.PRIMING) && statusResponse.getPodProgressStatus().equals(PodProgressStatus.READY_FOR_BASAL_SCHEDULE)) { + if (podState.getSetupProgress().equals(SetupProgress.PRIMING) && statusResponse.getPodProgressStatus().equals(PodProgressStatus.PRIMING_COMPLETED)) { if (LOG.isDebugEnabled()) { LOG.debug("Updating SetupProgress from PRIMING to PRIMING_FINISHED"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java index b6c81196c6..45cc9fc76e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java @@ -56,8 +56,8 @@ public class SetupPodAction implements OmnipodAction { if(setupPodResponse.getAddress() != podState.getAddress()) { throw new IllegalMessageAddressException(podState.getAddress(), setupPodResponse.getAddress()); } - if (setupPodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_SUCCESS) { - throw new IllegalPodProgressException(PodProgressStatus.PAIRING_SUCCESS, setupPodResponse.getPodProgressStatus()); + if (setupPodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_COMPLETED) { + throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, setupPodResponse.getPodProgressStatus()); } podState.setSetupProgress(SetupProgress.POD_CONFIGURED); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java index 4bd9780118..1ee1307bd4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodProgressStatus.java @@ -1,22 +1,22 @@ package info.nightscout.androidaps.plugins.pump.omnipod.defs; public enum PodProgressStatus { - INITIAL_VALUE((byte) 0x00), - TANK_POWER_ACTIVATED((byte) 0x01), - TANK_FILL_COMPLETED((byte) 0x02), - PAIRING_SUCCESS((byte) 0x03), + INITIALIZED((byte) 0x00), + MEMORY_INITIALIZED((byte) 0x01), + REMINDER_INITIALIZED((byte) 0x02), + PAIRING_COMPLETED((byte) 0x03), PRIMING((byte) 0x04), - READY_FOR_BASAL_SCHEDULE((byte) 0x05), - READY_FOR_CANNULA_INSERTION((byte) 0x06), - CANNULA_INSERTING((byte) 0x07), - RUNNING_ABOVE_FIFTY_UNITS((byte) 0x08), - RUNNING_BELOW_FIFTY_UNITS((byte) 0x09), - ONE_NOT_USED_BUT_IN_33((byte) 0x0a), - TWO_NOT_USED_BUT_IN_33((byte) 0x0b), - THREE_NOT_USED_BUT_IN_33((byte) 0x0c), - FAULT_EVENT_OCCURRED((byte) 0x0d), - FAILED_TO_INITIALIZE_IN_TIME((byte) 0x0e), - INACTIVE((byte) 0x0f); + PRIMING_COMPLETED((byte) 0x05), + BASAL_INITIALIZED((byte) 0x06), + INSERTING_CANNULA((byte) 0x07), + ABOVE_FIFTY_UNITS((byte) 0x08), + FIFTY_OR_LESS_UNITS((byte) 0x09), + ONE_NOT_USED((byte) 0x0a), + TWO_NOT_USED((byte) 0x0b), + THREE_NOT_USED((byte) 0x0c), + FAULT_EVENT_OCCURRED((byte) 0x0d), // Fault event occurred (a "screamer") + ACTIVATION_TIME_EXCEEDED((byte) 0x0e), // Took > 2 hours from progress 2 to 3 or > 1 hour from 3 to 8 + INACTIVE((byte) 0x0f); // Pod deactivated or a fatal packet state error private byte value; @@ -38,6 +38,6 @@ public enum PodProgressStatus { } public boolean isReadyForDelivery() { - return this == RUNNING_ABOVE_FIFTY_UNITS || this == RUNNING_BELOW_FIFTY_UNITS; + return this == ABOVE_FIFTY_UNITS || this == FIFTY_OR_LESS_UNITS; } } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java index 84697c0462..e2bf96ffde 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/ErrorResponseTest.java @@ -45,7 +45,7 @@ public class ErrorResponseTest { ErrorResponse errorResponse = new ErrorResponse(ByteUtil.fromHexString("0603101308")); assertEquals(0x10, errorResponse.getErrorResponseCode()); assertEquals(FaultEventCode.MESSAGE_LENGTH_TOO_LONG, errorResponse.getFaultEventCode()); - assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, errorResponse.getPodProgressStatus()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorResponse.getPodProgressStatus()); assertNull(errorResponse.getNonceSearchKey()); } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponseTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponseTest.java index d5a79e9ffd..a931ad7b1d 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponseTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/StatusResponseTest.java @@ -42,7 +42,7 @@ public class StatusResponseTest { StatusResponse statusResponse = new StatusResponse(bytes); assertEquals(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus()); - assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, statusResponse.getPodProgressStatus()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, statusResponse.getPodProgressStatus()); assertNull("Reservoir level should be null", statusResponse.getReservoirLevel()); assertEquals(Duration.standardMinutes(1307).getMillis(), statusResponse.getTimeActive().getMillis()); assertEquals(60.05, statusResponse.getInsulinDelivered(), 0.000001); @@ -59,7 +59,7 @@ public class StatusResponseTest { StatusResponse statusResponse = new StatusResponse(bytes); assertEquals(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus()); - assertEquals(PodProgressStatus.RUNNING_BELOW_FIFTY_UNITS, statusResponse.getPodProgressStatus()); + assertEquals(PodProgressStatus.FIFTY_OR_LESS_UNITS, statusResponse.getPodProgressStatus()); assertEquals(24.4, statusResponse.getReservoirLevel(), 0.000001); assertEquals(Duration.standardMinutes(4261).getMillis(), statusResponse.getTimeActive().getMillis()); assertEquals(156.7, statusResponse.getInsulinDelivered(), 0.000001); @@ -93,7 +93,7 @@ public class StatusResponseTest { assertTrue(Duration.standardMinutes(3547).isEqual(statusResponse.getTimeActive())); assertEquals(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus()); - assertEquals(PodProgressStatus.RUNNING_BELOW_FIFTY_UNITS, statusResponse.getPodProgressStatus()); + assertEquals(PodProgressStatus.FIFTY_OR_LESS_UNITS, statusResponse.getPodProgressStatus()); assertEquals(129.45, statusResponse.getInsulinDelivered(), 0.00001); assertEquals(46.00, statusResponse.getReservoirLevel(), 0.00001); assertEquals(2.2, statusResponse.getInsulinNotDelivered(), 0.0001); diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java index 891ad81329..4ef96e38ed 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/VersionResponseTest.java @@ -72,7 +72,7 @@ public class VersionResponseTest { assertEquals(0x1f00ee87, versionResponse.getAddress()); assertEquals(41847, versionResponse.getLot()); assertEquals(240439, versionResponse.getTid()); - assertEquals(PodProgressStatus.PAIRING_SUCCESS, versionResponse.getPodProgressStatus()); + assertEquals(PodProgressStatus.PAIRING_COMPLETED, versionResponse.getPodProgressStatus()); assertEquals("2.7.0", versionResponse.getPiVersion().toString()); assertEquals("2.7.0", versionResponse.getPmVersion().toString()); assertNull(versionResponse.getRssi()); diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java index 528ac6a9a5..4a1893b23f 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/message/response/podinfo/PodInfoFaultEventTest.java @@ -20,7 +20,7 @@ public class PodInfoFaultEventTest { public void testPodInfoFaultEventNoFaultAlerts() { PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("02080100000a003800000003ff008700000095ff0000")); - assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatus()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatus()); assertEquals(DeliveryStatus.NORMAL, podInfoFaultEvent.getDeliveryStatus()); assertEquals(0, podInfoFaultEvent.getInsulinNotDelivered(), 0.000001); assertEquals(0x0a, podInfoFaultEvent.getPodMessageCounter()); @@ -51,7 +51,7 @@ public class PodInfoFaultEventTest { assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); assertFalse(podInfoFaultEvent.isFaultAccessingTables()); assertEquals(LogEventErrorCode.NONE, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.READY_FOR_BASAL_SCHEDULE, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); + assertEquals(PodProgressStatus.PRIMING_COMPLETED, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); assertEquals(46, podInfoFaultEvent.getRadioRSSI()); } @@ -71,7 +71,7 @@ public class PodInfoFaultEventTest { assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); assertFalse(podInfoFaultEvent.isFaultAccessingTables()); assertEquals(LogEventErrorCode.NONE, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); assertEquals(0, podInfoFaultEvent.getReceiverLowGain()); assertEquals(35, podInfoFaultEvent.getRadioRSSI()); } @@ -91,7 +91,7 @@ public class PodInfoFaultEventTest { assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); assertFalse(podInfoFaultEvent.isFaultAccessingTables()); assertEquals(LogEventErrorCode.INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_2, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); assertEquals(39, podInfoFaultEvent.getRadioRSSI()); } @@ -111,7 +111,7 @@ public class PodInfoFaultEventTest { assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); assertFalse(podInfoFaultEvent.isFaultAccessingTables()); assertEquals(LogEventErrorCode.INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_2, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); assertEquals(39, podInfoFaultEvent.getRadioRSSI()); } From 79d64dff6456a38e7780b57a7c40a314fc90eb71 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 3 May 2020 13:31:19 +0200 Subject: [PATCH 11/15] Use static Pod address in between pairing retries and remove unused methods from OmnipodUtil --- .../pump/omnipod/comm/OmnipodManager.java | 4 + .../omnipod/dialogs/PodManagementActivity.kt | 2 +- .../driver/comm/AapsOmnipodManager.java | 23 ++++-- .../pump/omnipod/util/OmnipodConst.java | 1 + .../pump/omnipod/util/OmnipodUtil.java | 77 ++++++------------- 5 files changed, 45 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java index 0c30d2f6c4..16962dd567 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java @@ -597,6 +597,10 @@ public class OmnipodManager { return 0x1f000000 | (new Random().nextInt() & 0x000fffff); } + public static boolean isValidAddress(int address) { + return (0x1f000000 | (address & 0x000fffff)) == address; + } + public static class BolusCommandResult { private final CommandDeliveryStatus commandDeliveryStatus; private final SingleSubject deliveryResultSubject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt index 12a08605c3..47c9a36ca5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt @@ -144,7 +144,7 @@ class PodManagementActivity : NoSplashAppCompatActivity() { val isPodSessionActive = (OmnipodUtil.getPodSessionState() != null) initpod_remove_pod.isEnabled = isPodSessionActive - initpod_reset_pod.isEnabled = isPodSessionActive + initpod_reset_pod.isEnabled = isPodSessionActive || OmnipodUtil.hasNextPodAddress() if (OmnipodUtil.getDriverState() == OmnipodDriverState.NotInitalized) { // if rileylink is not running we disable all operations diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 354ffc3f48..7d7337dba6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -84,6 +84,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface private static AapsOmnipodManager instance; private OmnipodPumpStatus pumpStatus; + private Integer nextPodAddress; private Date lastBolusTime; private Double lastBolusUnits; @@ -98,6 +99,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface OmnipodUtil.setPodSessionState(podSessionState); updatePumpStatus(podSessionState); }); + this.nextPodAddress = OmnipodUtil.getNextPodAddress(); this.pumpStatus = _pumpStatus; instance = this; } @@ -171,8 +173,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface long time = System.currentTimeMillis(); if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) { try { - // BS FIXME use static address for retries - int address = OmnipodManager.generateRandomAddress(); + int address = obtainNextPodAddress(); Disposable disposable = delegate.pairAndPrime(address).subscribe(res -> // handleSetupActionResult(podInitActionType, podInitReceiver, res, time, null)); @@ -279,6 +280,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface reportImplicitlyCanceledTbr(); OmnipodUtil.setPodSessionState(null); + OmnipodUtil.removeNextPodAddress(); addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.ResetPodState, null); @@ -544,18 +546,15 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface } } - - public long addSuccessToHistory(long requestTime, PodHistoryEntryType entryType, Object data) { + private long addSuccessToHistory(long requestTime, PodHistoryEntryType entryType, Object data) { return addToHistory(requestTime, entryType, data, true); } - public long addFailureToHistory(long requestTime, PodHistoryEntryType entryType, Object data) { + private long addFailureToHistory(long requestTime, PodHistoryEntryType entryType, Object data) { return addToHistory(requestTime, entryType, data, false); } - - public long addToHistory(long requestTime, PodHistoryEntryType entryType, Object data, boolean success) { - + private long addToHistory(long requestTime, PodHistoryEntryType entryType, Object data, boolean success) { PodHistory podHistory = new PodHistory(requestTime, entryType); if (data != null) { @@ -572,7 +571,15 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface MainApp.getDbHelper().createOrUpdate(podHistory); return podHistory.getPumpId(); + } + private int obtainNextPodAddress() { + if(nextPodAddress == null) { + nextPodAddress = OmnipodManager.generateRandomAddress(); + OmnipodUtil.setNextPodAddress(nextPodAddress); + } + + return nextPodAddress; } private void handleSetupActionResult(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, SetupActionResult res, long time, Profile profile) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java index f7b78250c3..d12fbd31df 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java @@ -14,6 +14,7 @@ public class OmnipodConst { public class Prefs { public static final String PodState = Prefix + "pod_state"; + public static final String NextPodAddress = Prefix + "next_pod_address"; public static final int BeepBasalEnabled = R.string.key_omnipod_beep_basal_enabled; public static final int BeepBolusEnabled = R.string.key_omnipod_beep_bolus_enabled; public static final int BeepSMBEnabled = R.string.key_omnipod_beep_smb_enabled; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java index a7035ac4e5..96f5e39861 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java @@ -26,6 +26,7 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodPodType; @@ -38,6 +39,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDevice import info.nightscout.androidaps.plugins.pump.omnipod.service.RileyLinkOmnipodService; import info.nightscout.androidaps.plugins.pump.omnipod_dash.OmnipodDashPumpPlugin; import info.nightscout.androidaps.utils.OKDialog; +import info.nightscout.androidaps.utils.SP; /** * Created by andy on 4/8/19. @@ -47,7 +49,6 @@ public class OmnipodUtil extends RileyLinkUtil { private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); - private static boolean lowLevelDebug = true; private static RileyLinkOmnipodService omnipodService; private static OmnipodPumpStatus omnipodPumpStatus; private static OmnipodCommandType currentCommand; @@ -63,61 +64,14 @@ public class OmnipodUtil extends RileyLinkUtil { return gsonInstance; } - public static int makeUnsignedShort(int b2, int b1) { - int k = (b2 & 0xff) << 8 | b1 & 0xff; - return k; - } - - public static byte[] getByteArrayFromUnsignedShort(int shortValue, boolean returnFixedSize) { - byte highByte = (byte) (shortValue >> 8 & 0xFF); - byte lowByte = (byte) (shortValue & 0xFF); - - if (highByte > 0) { - return createByteArray(highByte, lowByte); - } else { - return returnFixedSize ? createByteArray(highByte, lowByte) : createByteArray(lowByte); - } - - } - - - public static byte[] createByteArray(byte... data) { - return data; - } - - - public static byte[] createByteArray(List data) { - - byte[] array = new byte[data.size()]; - - for (int i = 0; i < data.size(); i++) { - array[i] = data.get(i); - } - - return array; - } - - - public static boolean isLowLevelDebug() { - return lowLevelDebug; - } - - - public static void setLowLevelDebug(boolean lowLevelDebug) { - OmnipodUtil.lowLevelDebug = lowLevelDebug; - } - - public static OmnipodCommunicationManagerInterface getOmnipodCommunicationManager() { return (OmnipodCommunicationManagerInterface) RileyLinkUtil.rileyLinkCommunicationManager; } - public static RileyLinkOmnipodService getOmnipodService() { return OmnipodUtil.omnipodService; } - public static void setOmnipodService(RileyLinkOmnipodService medtronicService) { OmnipodUtil.omnipodService = medtronicService; } @@ -126,24 +80,20 @@ public class OmnipodUtil extends RileyLinkUtil { return OmnipodUtil.currentCommand; } - // FIXME public static void setCurrentCommand(OmnipodCommandType currentCommand) { OmnipodUtil.currentCommand = currentCommand; if (currentCommand != null) historyRileyLink.add(new RLHistoryItem(currentCommand)); - } - public static boolean isSame(Double d1, Double d2) { double diff = d1 - d2; return (Math.abs(diff) <= 0.000001); } - public static void displayNotConfiguredDialog(Context context) { OKDialog.show(context, MainApp.gs(R.string.combo_warning), MainApp.gs(R.string.omnipod_error_operation_not_possible_no_configuration), null); @@ -239,7 +189,6 @@ public class OmnipodUtil extends RileyLinkUtil { return OmnipodDashPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); } - public static void setPumpType(PumpType pumpType) { OmnipodUtil.pumpType = pumpType; } @@ -247,4 +196,26 @@ public class OmnipodUtil extends RileyLinkUtil { public static PumpType getPumpType() { return pumpType; } + + public static Integer getNextPodAddress() { + if(SP.contains(OmnipodConst.Prefs.NextPodAddress)) { + int nextPodAddress = SP.getInt(OmnipodConst.Prefs.NextPodAddress, 0); + if (OmnipodManager.isValidAddress(nextPodAddress)) { + return nextPodAddress; + } + } + return null; + } + + public static boolean hasNextPodAddress() { + return getNextPodAddress() != null; + } + + public static void setNextPodAddress(int address) { + SP.putInt(OmnipodConst.Prefs.NextPodAddress, address); + } + + public static void removeNextPodAddress() { + SP.remove(OmnipodConst.Prefs.NextPodAddress); + } } From e01ac6f6bec2c5b0f06e8ad6e92736485fb91a3d Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 3 May 2020 13:37:50 +0200 Subject: [PATCH 12/15] Fix failing Omnipod test cases --- .../driver/comm/AapsOmnipodManagerTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManagerTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManagerTest.java index 9d57b3ac45..5def4c92d4 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManagerTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManagerTest.java @@ -92,7 +92,7 @@ public class AapsOmnipodManagerTest { Profile profile = mock(Profile.class); Profile.ProfileValue value = mock(Profile.ProfileValue.class); - value.timeAsSeconds = 500; + value.timeAsSeconds = 1800; value.value = 0.5D; when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{ @@ -144,20 +144,20 @@ public class AapsOmnipodManagerTest { } @Test - public void invalidProfileUnsupportedPrecision() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Unsupported basal rate precision"); - + public void roundsToSupportedPrecision() { Profile profile = mock(Profile.class); Profile.ProfileValue value = mock(Profile.ProfileValue.class); - value.timeAsSeconds = 500; + value.timeAsSeconds = 0; value.value = 0.04D; when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{ value, }); - AapsOmnipodManager.mapProfileToBasalSchedule(profile); + BasalSchedule basalSchedule = AapsOmnipodManager.mapProfileToBasalSchedule(profile); + BasalScheduleEntry basalScheduleEntry = basalSchedule.getEntries().get(0); + + assertEquals(0.05D, basalScheduleEntry.getRate(), 0.000001); } } \ No newline at end of file From b67663894226ee019d3f0e2a669aba133a34123c Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 3 May 2020 13:43:06 +0200 Subject: [PATCH 13/15] Remove next pod address after succesful pairing --- .../pump/omnipod/driver/comm/AapsOmnipodManager.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 7d7337dba6..9f50ca34fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -177,6 +177,9 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface Disposable disposable = delegate.pairAndPrime(address).subscribe(res -> // handleSetupActionResult(podInitActionType, podInitReceiver, res, time, null)); + + removeNextPodAddress(); + return new PumpEnactResult().success(true).enacted(true); } catch (Exception ex) { String comment = handleAndTranslateException(ex); @@ -582,6 +585,11 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return nextPodAddress; } + private void removeNextPodAddress() { + nextPodAddress = null; + OmnipodUtil.removeNextPodAddress(); + } + private void handleSetupActionResult(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, SetupActionResult res, long time, Profile profile) { String comment = null; switch (res.getResultType()) { From 5b96e1823422eab09b8e10cf9c406523bd567035 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 3 May 2020 13:50:11 +0200 Subject: [PATCH 14/15] Don't log full stack trace of ignored Exception in OmnipodCommunicationService.exchangePackets --- .../plugins/pump/omnipod/comm/OmnipodCommunicationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java index d610c43ddb..6deeae13fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationService.java @@ -319,7 +319,7 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { response = sendAndListen(packet, responseTimeoutMilliseconds, repeatCount, 9, preambleExtensionMilliseconds, OmnipodPacket.class); } catch (RileyLinkCommunicationException | OmnipodException ex) { if (isLoggingEnabled()) { - LOG.debug("Ignoring exception in exchangePackets", ex); + LOG.debug("Ignoring exception in exchangePackets: "+ ex.getClass().getSimpleName() +": "+ ex.getMessage()); } } catch (Exception ex) { throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex); From 57be461fd4b2d1663cc0d1df0b39fdb66d5f5364 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sun, 3 May 2020 13:59:33 +0200 Subject: [PATCH 15/15] Don't keep next Pod address in AapsOmnipodManager --- .../plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index 9f50ca34fb..27291a07ef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -84,7 +84,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface private static AapsOmnipodManager instance; private OmnipodPumpStatus pumpStatus; - private Integer nextPodAddress; private Date lastBolusTime; private Double lastBolusUnits; @@ -99,7 +98,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface OmnipodUtil.setPodSessionState(podSessionState); updatePumpStatus(podSessionState); }); - this.nextPodAddress = OmnipodUtil.getNextPodAddress(); this.pumpStatus = _pumpStatus; instance = this; } @@ -577,6 +575,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface } private int obtainNextPodAddress() { + Integer nextPodAddress = OmnipodUtil.getNextPodAddress(); if(nextPodAddress == null) { nextPodAddress = OmnipodManager.generateRandomAddress(); OmnipodUtil.setNextPodAddress(nextPodAddress); @@ -586,7 +585,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface } private void removeNextPodAddress() { - nextPodAddress = null; OmnipodUtil.removeNextPodAddress(); }