From 88516e2bb67fa7888f03a5489d0b8a92de6ddc82 Mon Sep 17 00:00:00 2001 From: Pogman <subaziro@gmail.com> Date: Sat, 18 Feb 2017 16:08:31 +0000 Subject: [PATCH] Fixes to stop the CNL from going into an error state: 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 --- .../message/ContourNextLinkMessage.java | 52 ++++++++++++++++++- .../medtronic/message/EHSMMessage.java | 10 ++++ .../message/PumpStatusRequestMessage.java | 6 ++- .../message/PumpTimeRequestMessage.java | 8 ++- .../message/PumpTimeResponseMessage.java | 6 ++- 5 files changed, 76 insertions(+), 6 deletions(-) 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 0d35809..86305a3 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 d930a59..0e06453 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 982bdba..32e1479 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 24cbb14..6aa7772 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 06d88ce..2a816cc 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); -- GitLab