Add some checks and logging in Omnipod packet and message exchange

This commit is contained in:
Bart Sopers 2020-04-26 21:11:47 +02:00
parent 37c1d30ecc
commit 9a5cd3c902
7 changed files with 88 additions and 24 deletions

View file

@ -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 // 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 // This happens when we simply didn't need to send any commands to the pump
return false;
} }
} }
return false; return false;

View file

@ -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.hw.rileylink.ble.defs.RileyLinkBLEError;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; 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.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.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodPacket; 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.PacketType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; 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.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.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. * Created by andy on 6/29/18.
@ -153,6 +154,8 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
packetAddress = addressOverride; packetAddress = addressOverride;
} }
podState.increaseMessageNumber();
boolean firstPacket = true; boolean firstPacket = true;
byte[] encodedMessage; byte[] encodedMessage;
// this does not work well with the deactivate pod command, we somehow either // 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) { if (response.getPacketType() == PacketType.ACK) {
podState.increasePacketNumber(1);
throw new IllegalPacketTypeException(null, PacketType.ACK); throw new IllegalPacketTypeException(null, PacketType.ACK);
} }
@ -216,6 +218,9 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
while (receivedMessage == null) { while (receivedMessage == null) {
try { try {
receivedMessage = OmnipodMessage.decodeMessage(receivedMessageData); receivedMessage = OmnipodMessage.decodeMessage(receivedMessageData);
if (receivedMessage.getSequenceNumber() != podState.getMessageNumber()) {
throw new IllegalSequenceNumberException(podState.getMessageNumber(), receivedMessage.getSequenceNumber());
}
} catch (NotEnoughDataException ex) { } catch (NotEnoughDataException ex) {
// Message is (probably) not complete yet // Message is (probably) not complete yet
OmnipodPacket ackForCon = createAckPacket(podState, packetAddress, ackAddressOverride); OmnipodPacket ackForCon = createAckPacket(podState, packetAddress, ackAddressOverride);
@ -235,8 +240,6 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
} }
} }
podState.increaseMessageNumber(2);
ackUntilQuiet(podState, packetAddress, ackAddressOverride); ackUntilQuiet(podState, packetAddress, ackAddressOverride);
List<MessageBlock> messageBlocks = receivedMessage.getMessageBlocks(); List<MessageBlock> 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) { 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); throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
} }
podState.increasePacketNumber(1); podState.increasePacketNumber();
} }
private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet) { 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) { private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet, int repeatCount, int responseTimeoutMilliseconds, int exchangeTimeoutMilliseconds, int preambleExtensionMilliseconds) {
long timeoutTime = System.currentTimeMillis() + exchangeTimeoutMilliseconds; long timeoutTime = System.currentTimeMillis() + exchangeTimeoutMilliseconds;
podState.increasePacketNumber();
while (System.currentTimeMillis() < timeoutTime) { while (System.currentTimeMillis() < timeoutTime) {
OmnipodPacket response = null; OmnipodPacket response = null;
try { try {
@ -311,17 +322,34 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
} catch (Exception ex) { } catch (Exception ex) {
throw new CommunicationException(CommunicationException.Type.UNEXPECTED_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; continue;
} }
if (response.getAddress() != packet.getAddress()) { if (response.getAddress() != packet.getAddress()) {
continue; if (isLoggingEnabled()) {
LOG.debug("Packet address " + response.getAddress() + " doesn't match " + packet.getAddress());
} }
if (response.getSequenceNumber() != ((podState.getPacketNumber() + 1) & 0b11111)) {
continue; 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; return response;
} }
throw new CommunicationException(CommunicationException.Type.TIMEOUT); throw new CommunicationException(CommunicationException.Type.TIMEOUT);

View file

@ -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;
}
}

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.message; 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.hw.rileylink.ble.data.RLMessage;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType;
@ -79,4 +81,14 @@ public class OmnipodPacket implements RLMessage {
return valid; return valid;
} }
@Override
public String toString() {
return "OmnipodPacket{" +
"packetAddress=" + packetAddress +
", packetType=" + packetType +
", sequenceNumber=" + sequenceNumber +
", encodedMessage=" + ByteUtil.shortHexStringWithoutSpaces(encodedMessage) +
", valid=" + valid +
'}';
}
} }

View file

@ -46,12 +46,12 @@ public abstract class PodState {
this.packetNumber = packetNumber; this.packetNumber = packetNumber;
} }
public void increaseMessageNumber(int increment) { public void increaseMessageNumber() {
setMessageNumber((messageNumber + increment) & 0b1111); setMessageNumber((messageNumber + 1) & 0b1111);
} }
public void increasePacketNumber(int increment) { public void increasePacketNumber() {
setPacketNumber((packetNumber + increment) & 0b11111); setPacketNumber((packetNumber + 1) & 0b11111);
} }
public boolean hasFaultEvent() { public boolean hasFaultEvent() {

View file

@ -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.OmnipodCommunicationService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; 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.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.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; 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); comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state);
} else if (ex instanceof IllegalResponseException) { } else if (ex instanceof IllegalResponseException) {
comment = getStringResource(R.string.omnipod_driver_error_invalid_response); 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) { } else if (ex instanceof MessageDecodingException) {
comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed); comment = getStringResource(R.string.omnipod_driver_error_message_decoding_failed);
} else if (ex instanceof NonceOutOfSyncException) { } else if (ex instanceof NonceOutOfSyncException) {

View file

@ -1756,6 +1756,7 @@
<string name="omnipod_driver_error_invalid_packet_type">Communication failed: received an invalid packet from the Pod.</string> <string name="omnipod_driver_error_invalid_packet_type">Communication failed: received an invalid packet from the Pod.</string>
<string name="omnipod_driver_error_invalid_progress_state">Communication failed: the Pod is in a wrong state.</string> <string name="omnipod_driver_error_invalid_progress_state">Communication failed: the Pod is in a wrong state.</string>
<string name="omnipod_driver_error_invalid_response">Communication failed: received an invalid response from the Pod.</string> <string name="omnipod_driver_error_invalid_response">Communication failed: received an invalid response from the Pod.</string>
<string name="omnipod_driver_error_invalid_sequence_number">Communication failed: received a message with an invalid sequence number from the Pod.</string>
<string name="omnipod_driver_error_message_decoding_failed">Communication failed: failed to decode message from the Pod.</string> <string name="omnipod_driver_error_message_decoding_failed">Communication failed: failed to decode message from the Pod.</string>
<string name="omnipod_driver_error_nonce_resync_failed">Communication failed: nonce resync failed.</string> <string name="omnipod_driver_error_nonce_resync_failed">Communication failed: nonce resync failed.</string>
<string name="omnipod_driver_error_nonce_out_of_sync">Communication failed: nonce out of sync.</string> <string name="omnipod_driver_error_nonce_out_of_sync">Communication failed: nonce out of sync.</string>