Pad NonceResyncableMessageBlock with GetStatusCommands to ensure > 1 packet in order to improve command verification

This commit is contained in:
Bart Sopers 2019-12-21 02:01:22 +01:00
parent 78d789db4e
commit 1dd296ef0e
3 changed files with 39 additions and 22 deletions

View file

@ -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) {

View file

@ -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 {

View file

@ -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<MessageBlock> 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<MessageBlock> 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<MessageBlock> 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) {