From 1dd296ef0ef834d2a0218e19bd773d5256dd5169 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sat, 21 Dec 2019 02:01:22 +0100 Subject: [PATCH] Pad NonceResyncableMessageBlock with GetStatusCommands to ensure > 1 packet in order to improve command verification --- .../comm/OmnipodCommunicationService.java | 15 +++++++- .../pump/omnipod/comm/OmnipodManager.java | 12 ------- .../omnipod/comm/message/OmnipodMessage.java | 34 ++++++++++++++----- 3 files changed, 39 insertions(+), 22 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 81fd2256f5..6a7c135565 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 @@ -148,7 +148,20 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager { } boolean firstPacket = true; - byte[] encodedMessage = message.getEncoded(); + byte[] encodedMessage; + if (message.isNonceResyncable()) { + OmnipodMessage paddedMessage = new OmnipodMessage(message); + // If messages are nonce resyncable, we want do distinguish between certain and uncertain failures for verification purposes + // However, some commands (e.g. cancel delivery) are single packet command by nature. When we get a timeout with a single packet, + // we are unsure whether or not the command was received by the pod + // However, if we send > 1 packet, we know that the command wasn't received if we never send the subsequent packets, + // because the last packet contains the CRC. + // So we pad the message with get status commands to make it > packet + paddedMessage.padWithGetStatusCommands(PacketType.PDM.getMaxBodyLength()); // First packet is of type PDM + encodedMessage = paddedMessage.getEncoded(); + } else { + encodedMessage = message.getEncoded(); + } OmnipodPacket response = null; while (encodedMessage.length > 0) { 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 a3b078d741..4def104ded 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 @@ -221,18 +221,6 @@ public class OmnipodManager { logStartingCommandExecution("cancelDelivery [deliveryTypes=" + deliveryTypes + ", acknowledgementBeep=" + acknowledgementBeep + "]"); - try { - // As the cancel delivery command is a single packet command, - // first verify that the pod is reachable by obtaining a status response - // FIXME replace this with padding the CancelDelivery command message - // with GetStatusResponse commands to ensure that the message > 1 packets - StatusResponse podStatus = getPodStatus(); - } catch (OmnipodException ex) { - logCommandExecutionFinished("cancelDelivery"); - ex.setCertainFailure(true); - throw ex; - } - try { executeAndVerify(() -> communicationService.executeAction(new CancelDeliveryAction(podState, deliveryTypes, acknowledgementBeep))); } finally { 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 646b3dd205..d5329ac312 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 @@ -1,14 +1,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.message; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.GetStatusCommand; import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.exception.CrcMismatchException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.MessageDecodingException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.NotEnoughDataException; @@ -16,11 +14,16 @@ import info.nightscout.androidaps.plugins.pump.omnipod.util.OmniCRC; public class OmnipodMessage { - private static final Logger LOG = LoggerFactory.getLogger(OmnipodCommunicationService.class); private final int address; private final List messageBlocks; private final int sequenceNumber; + public OmnipodMessage(OmnipodMessage other) { + address = other.address; + messageBlocks = new ArrayList<>(other.messageBlocks); + sequenceNumber = other.sequenceNumber; + } + public OmnipodMessage(int address, List messageBlocks, int sequenceNumber) { this.address = address; this.messageBlocks = messageBlocks; @@ -88,6 +91,12 @@ public class OmnipodMessage { return encodedData; } + public void padWithGetStatusCommands(int packetSize) { + while (getEncoded().length < packetSize) { + messageBlocks.add(new GetStatusCommand(PodInfoType.NORMAL)); + } + } + public List getMessageBlocks() { return messageBlocks; } @@ -106,14 +115,21 @@ public class OmnipodMessage { } public boolean isNonceResyncable() { - return messageBlocks.size() > 0 && (messageBlocks.get(0) instanceof NonceResyncableMessageBlock); + for (MessageBlock messageBlock : messageBlocks) { + if (messageBlock instanceof NonceResyncableMessageBlock) { + return true; + } + } + return false; } public int getSentNonce() { - if (!isNonceResyncable()) { - throw new UnsupportedOperationException("Message is not nonce resyncable"); + for (MessageBlock messageBlock : messageBlocks) { + if (messageBlock instanceof NonceResyncableMessageBlock) { + return ((NonceResyncableMessageBlock) messageBlock).getNonce(); + } } - return ((NonceResyncableMessageBlock) messageBlocks.get(0)).getNonce(); + throw new UnsupportedOperationException("Message is not nonce resyncable"); } public void resyncNonce(int nonce) {