diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java index 0d358090e414caec209005169b6d089cd38f7cf8..86305a33b9cb21f99c88d105b78b2b35a90c7b0a 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java @@ -20,7 +20,7 @@ public abstract class ContourNextLinkMessage { private static final String TAG = ContourNextLinkMessage.class.getSimpleName(); private static final int USB_BLOCKSIZE = 64; - private static final int READ_TIMEOUT_MS = 10000; + private static final int READ_TIMEOUT_MS = 15000; //ASTM standard is 15 seconds (note was previously set at 10 seconds) private static final String BAYER_USB_HEADER = "ABC"; protected ByteBuffer mPayload; @@ -142,6 +142,56 @@ public abstract class ContourNextLinkMessage { return responseMessage.toByteArray(); } + // safety check to make sure a expected 0x81 response is received before next expected 0x80 response + // very infrequent as clearMessage catches most issues but very important to save a CNL error situation + + protected int readMessage_0x81(UsbHidDriver mDevice) throws IOException, TimeoutException { + + int responseSize = 0; + boolean doRetry; + do { + byte[] responseBytes = readMessage(mDevice); + if (responseBytes[18] != (byte) 0x81) { + doRetry = true; + Log.d(TAG, "readMessage0x81: did not get 0x81 response, got " + responseBytes[18]); + } else { + doRetry = false; + responseSize = responseBytes.length; + } + + } while (doRetry); + + return responseSize; + } + + // intercept unexpected messages from the CNL + // these usually come from pump requests as it can occasionally resend message responses several times (possibly due to a missed CNL ACK during CNL-PUMP comms?) + // mostly noted on the higher radio channels, channel 26 shows this the most + // if these messages are not cleared the CNL will likely error needing to be unplugged to reset as it expects them to be read before any further commands are sent + + protected int clearMessage(UsbHidDriver mDevice) throws IOException { + + byte[] responseBuffer = new byte[USB_BLOCKSIZE]; + int bytesRead; + int bytesClear = 0; + + do { + bytesRead = mDevice.read(responseBuffer, 2000); + if (bytesRead > 0) { + bytesClear += bytesRead; + String responseString = HexDump.dumpHexString(responseBuffer); + Log.d(TAG, "READ: " + responseString); + } + } while (bytesRead > 0); + + if (bytesClear > 0) { + Log.d(TAG, "clearMessage: message stream cleared bytes: " + bytesClear); + } + + return bytesClear; + } + + public enum ASCII { STX(0x02), EOT(0x04), diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/EHSMMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/EHSMMessage.java index d930a59e3ae785b1bfec5255b3f914c1ffb2422f..0e064536b650efd76e2ee8dad5867a787671339f 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/EHSMMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/EHSMMessage.java @@ -20,6 +20,10 @@ public class EHSMMessage extends MedtronicSendMessageRequestMessage<ContourNext @Override public ContourNextLinkResponseMessage send(UsbHidDriver mDevice, int millis) throws IOException, TimeoutException, UnexpectedMessageException { + + // clear unexpected incoming messages + clearMessage(mDevice); + sendMessage(mDevice); if (millis > 0) { try { @@ -27,11 +31,17 @@ public class EHSMMessage extends MedtronicSendMessageRequestMessage<ContourNext } catch (InterruptedException e) { } } + // The End EHSM Session only has an 0x81 response + if (readMessage_0x81(mDevice) != 48) { + throw new UnexpectedMessageException("length of EHSMMessage response does not match"); + } +/* readMessage(mDevice); if (this.encode().length != 54) { throw new UnexpectedMessageException("length of EHSMMessage response does not match"); } +*/ return null; } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java index 982bdba7bb025a7dff5d690d190a2926f66da227..32e14796595cae2dfa1f35cf58916b257a39db0d 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java @@ -22,6 +22,10 @@ public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage } public PumpStatusResponseMessage send(UsbHidDriver mDevice, int millis) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException { + + // clear unexpected incoming messages + clearMessage(mDevice); + sendMessage(mDevice); if (millis > 0) { try { @@ -31,7 +35,7 @@ public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage } } // Read the 0x81 - readMessage(mDevice); + readMessage_0x81(mDevice); if (millis > 0) { try { Log.d(TAG, "waiting " + millis +" ms"); diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java index 24cbb144d87a530c034e5666127346298e3fcf70..6aa7772e46b02828deb579f190e7db402283edc1 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java @@ -19,6 +19,10 @@ public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage<P @Override public PumpTimeResponseMessage send(UsbHidDriver mDevice, int millis) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException { + + // clear unexpected incoming messages + clearMessage(mDevice); + sendMessage(mDevice); if (millis > 0) { try { @@ -27,7 +31,7 @@ public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage<P } } // Read the 0x81 - readMessage(mDevice); + readMessage_0x81(mDevice); if (millis > 0) { try { Thread.sleep(millis); @@ -44,4 +48,4 @@ public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage<P protected PumpTimeResponseMessage getResponse(byte[] payload) throws ChecksumException, EncryptionException, IOException, UnexpectedMessageException { return new PumpTimeResponseMessage(mPumpSession, payload); } -} +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java index 06d88ce206d0d88fa28fbda2bfb313c0d61131d6..2a816cc728f1fc505fc94884a170750f5bc81fa0 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeResponseMessage.java @@ -10,6 +10,7 @@ import info.nightscout.android.BuildConfig; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; +import info.nightscout.android.medtronic.exception.UnexpectedMessageException; import info.nightscout.android.utils.HexDump; /** @@ -20,14 +21,15 @@ public class PumpTimeResponseMessage extends MedtronicSendMessageResponseMessage private Date pumpTime; - protected PumpTimeResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + protected PumpTimeResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException, UnexpectedMessageException { super(pumpSession, payload); if (this.encode().length < (61 + 8)) { // Invalid message. Return an invalid date. // TODO - deal with this more elegantly Log.e(TAG, "Invalid message received for getPumpTime"); - pumpTime = new Date(); + throw new UnexpectedMessageException("Invalid message received for getPumpTime"); +// pumpTime = new Date(); } else { ByteBuffer dateBuffer = ByteBuffer.allocate(8); dateBuffer.order(ByteOrder.BIG_ENDIAN);