diff --git a/640gAndroidUploader.iml b/640gAndroidUploader.iml index dd11c422309587fbfb2c40dcfbc1c5c64bb0d573..21ad486e1dacdc31dfcf484957078ef9fbc29307 100644 --- a/640gAndroidUploader.iml +++ b/640gAndroidUploader.iml @@ -13,7 +13,7 @@ <content url="file://$MODULE_DIR$"> <excludeFolder url="file://$MODULE_DIR$/.gradle" /> </content> - <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" /> + <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> </module> \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java index 6dd908f0dd3f57b8d8c585d51690eaee4b82df5b..24b2c9b5793e2adc55cebc48b0ce999a008dd55e 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java @@ -32,6 +32,7 @@ import info.nightscout.android.medtronic.message.MedtronicMessage; import info.nightscout.android.medtronic.message.MessageUtils; import info.nightscout.android.medtronic.message.PumpBasalPatternRequestMessage; import info.nightscout.android.medtronic.message.PumpBasalPatternResponseMessage; +import info.nightscout.android.medtronic.message.ReadInfoRequestMessage; import info.nightscout.android.medtronic.message.PumpStatusRequestMessage; import info.nightscout.android.medtronic.message.PumpStatusResponseMessage; import info.nightscout.android.medtronic.message.PumpTimeRequestMessage; @@ -240,7 +241,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler { Log.d(TAG, "Finished enterPasshtroughMode"); } - public void openConnection() throws IOException, TimeoutException, NoSuchAlgorithmException { + public void openConnection() throws IOException, TimeoutException, NoSuchAlgorithmException, ChecksumException { Log.d(TAG, "Begin openConnection"); new ContourNextLinkBinaryMessage(ContourNextLinkBinaryMessage.CommandType.OPEN_CONNECTION, mPumpSession, mPumpSession.getHMAC()).send(this); // FIXME - We need to care what the response message is - wrong MAC and all that @@ -250,16 +251,11 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler { public void requestReadInfo() throws IOException, TimeoutException, EncryptionException, ChecksumException { Log.d(TAG, "Begin requestReadInfo"); - new ContourNextLinkBinaryMessage(ContourNextLinkBinaryMessage.CommandType.READ_INFO, mPumpSession, null).send(this); - ContourNextLinkMessage response = ReadInfoResponseMessage.fromBytes(mPumpSession, readMessage()); + ReadInfoResponseMessage response = new ReadInfoRequestMessage(mPumpSession).send(mDevice); - // FIXME - this needs to go into ReadInfoResponseMessage - ByteBuffer infoBuffer = ByteBuffer.allocate(16); - infoBuffer.order(ByteOrder.BIG_ENDIAN); - infoBuffer.put(response.encode(), 0x21, 16); - long linkMAC = infoBuffer.getLong(0); - long pumpMAC = infoBuffer.getLong(8); + long linkMAC = response.getLinkMAC(); + long pumpMAC = response.getPumpMAC(); this.getPumpSession().setLinkMAC(linkMAC); this.getPumpSession().setPumpMAC(pumpMAC); @@ -327,7 +323,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler { return mPumpSession.getRadioChannel(); } - public void beginEHSMSession() throws EncryptionException, IOException, TimeoutException { + public void beginEHSMSession() throws EncryptionException, IOException, TimeoutException, ChecksumException { Log.d(TAG, "Begin beginEHSMSession"); new BeginEHSMMessage(mPumpSession).send(this); // The Begin EHSM Session only has an 0x81 response @@ -492,7 +488,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler { Log.d(TAG, "Finished getBasalPatterns"); } - public void endEHSMSession() throws EncryptionException, IOException, TimeoutException { + public void endEHSMSession() throws EncryptionException, IOException, TimeoutException, ChecksumException { Log.d(TAG, "Begin endEHSMSession"); new EndEHSMMessage(mPumpSession).send(this); // The End EHSM Session only has an 0x81 response @@ -500,7 +496,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler { Log.d(TAG, "Finished endEHSMSession"); } - public void closeConnection() throws IOException, TimeoutException { + public void closeConnection() throws IOException, TimeoutException, ChecksumException { Log.d(TAG, "Begin closeConnection"); new ContourNextLinkBinaryMessage(ContourNextLinkBinaryMessage.CommandType.CLOSE_CONNECTION, mPumpSession, null).send(this); // FIXME - We need to care what the response message is - wrong MAC and all that diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java index e2ee643a1a0d9f7de0a0c566c6d2d147ad6e3e19..804ce6d2d75b17522bd6ef046229e33397104d65 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java @@ -1,12 +1,15 @@ package info.nightscout.android.medtronic.message; +import java.io.IOException; + +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 26/03/2016. */ -public class BeginEHSMMessage extends MedtronicSendMessage { - public BeginEHSMMessage(MedtronicCnlSession pumpSession) throws EncryptionException { +public class BeginEHSMMessage extends MedtronicRequestMessage { + public BeginEHSMMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.BEGIN_EHSM_SESSION, pumpSession, buildPayload()); } @@ -14,4 +17,9 @@ public class BeginEHSMMessage extends MedtronicSendMessage { // Not sure what the payload of a null byte means, but it's the same every time. return new byte[] { 0x00 }; } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java index eda3ce6f6f514f3045396216dc658b65e825e5fc..db32bac435844e3cb586cee8d192c8ee824f335e 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java @@ -9,7 +9,7 @@ import java.nio.ByteOrder; * Created by lgoedhart on 26/03/2016. */ public class ChannelNegotiateMessage extends MedtronicMessage { - public ChannelNegotiateMessage(MedtronicCnlSession pumpSession) { + public ChannelNegotiateMessage(MedtronicCnlSession pumpSession) throws ChecksumException { super(CommandType.SEND_MESSAGE, CommandAction.CHANNEL_NEGOTIATE, pumpSession, buildPayload(pumpSession)); } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java index 95e94baa56ef73718e3db0d2d13e272f8b48a058..4a3f94bd07cacac066df13a416f51f06b4e6e3d3 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java @@ -1,7 +1,9 @@ package info.nightscout.android.medtronic.message; +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Locale; @@ -9,11 +11,11 @@ import java.util.Locale; /** * Created by lgoedhart on 26/03/2016. */ -public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage{ +public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { //protected ByteBuffer mBayerEnvelope; //protected ByteBuffer mBayerPayload; - //protected MedtronicCNLSession mPumpSession; - //protected CommandType mCommandType = CommandType.NO_TYPE; + protected MedtronicCnlSession mPumpSession; + protected CommandType mCommandType = CommandType.NO_TYPE; static int ENVELOPE_SIZE = 33; @@ -40,8 +42,29 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage{ } } - public ContourNextLinkBinaryMessage(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) { + public ContourNextLinkBinaryMessage(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { super(buildPayload(commandType, pumpSession, payload)); + mCommandType = commandType; + mPumpSession = pumpSession; + + // Validate checksum + byte messageChecksum = this.mPayload.get(32); + byte calculatedChecksum = (byte) (MessageUtils.oneByteSum(this.mPayload.array()) - messageChecksum); + + if (messageChecksum != calculatedChecksum) { + throw new ChecksumException(String.format(Locale.getDefault(), "Expected to get %d. Got %d", (int) calculatedChecksum, (int) messageChecksum)); + } + } + + /** + * Handle incrementing sequence number + * + * @param mDevice + * @throws IOException + */ + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrBayerSequenceNumber(); } protected static byte[] buildPayload(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) { @@ -75,7 +98,12 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage{ public static ContourNextLinkMessage fromBytes(byte[] bytes) throws ChecksumException { ContourNextLinkMessage message = new ContourNextLinkMessage(bytes); + message.validate(); + + return message; + } + protected void validate(ContourNextLinkMessage message) throws ChecksumException { // Validate checksum byte messageChecksum = message.mPayload.get(32); byte calculatedChecksum = (byte) (MessageUtils.oneByteSum(message.mPayload.array()) - messageChecksum); @@ -84,6 +112,6 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage{ throw new ChecksumException(String.format(Locale.getDefault(), "Expected to get %d. Got %d", (int) calculatedChecksum, (int) messageChecksum)); } - return message; + } } 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 2a44cfdeede51c0ec2d21d6b6128aa17a04cbd10..2639e76c56591663bd69c1745892e11de2603ec9 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 @@ -1,32 +1,102 @@ package info.nightscout.android.medtronic.message; +import android.util.Log; + +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.concurrent.TimeoutException; + +import info.nightscout.android.USB.UsbHidDriver; +import info.nightscout.android.utils.HexDump; + +import static android.R.id.message; /** * Created by lgoedhart on 26/03/2016. */ public class ContourNextLinkMessage { + private static final String TAG = ContourNextLinkMessage.class.getSimpleName(); + + private static final int USB_BLOCKSIZE = 64; + private static final int READ_TIMEOUT_MS = 5000; + private static final String BAYER_USB_HEADER = "ABC"; + protected ByteBuffer mPayload; - public ContourNextLinkMessage(byte[] bytes) { - if (bytes != null) { - this.mPayload = ByteBuffer.allocate(bytes.length); - this.mPayload.put(bytes); - } + protected ContourNextLinkMessage(byte[] bytes) { + setPayload(bytes); } public byte[] encode() { return mPayload.array(); } + // TODO refactor public void send(ContourNextLinkMessageHandler handler) throws IOException { handler.sendMessage(this); } + // FIXME - get rid of this - make a Builder instead protected void setPayload(byte[] payload) { - mPayload = ByteBuffer.allocate(payload.length); - mPayload.put(payload); + if (payload != null) { + mPayload = ByteBuffer.allocate(payload.length); + mPayload.put(payload); + } + } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + int pos = 0; + byte[] message = this.encode(); + + while (message.length > pos) { + ByteBuffer outputBuffer = ByteBuffer.allocate(USB_BLOCKSIZE); + int sendLength = (pos + 60 > message.length) ? message.length - pos : 60; + outputBuffer.put(BAYER_USB_HEADER.getBytes()); + outputBuffer.put((byte) sendLength); + outputBuffer.put(message, pos, sendLength); + + mDevice.write(outputBuffer.array(), 200); + pos += sendLength; + + String outputString = HexDump.dumpHexString(outputBuffer.array()); + Log.d(TAG, "WRITE: " + outputString); + } } + + protected byte[] readMessage(UsbHidDriver mDevice) throws IOException, TimeoutException { + ByteArrayOutputStream responseMessage = new ByteArrayOutputStream(); + + byte[] responseBuffer = new byte[USB_BLOCKSIZE]; + int bytesRead; + int messageSize = 0; + + do { + bytesRead = mDevice.read(responseBuffer, READ_TIMEOUT_MS); + + if (bytesRead == -1) { + throw new TimeoutException("Timeout waiting for response from pump"); + } else if (bytesRead > 0) { + // Validate the header + ByteBuffer header = ByteBuffer.allocate(3); + header.put(responseBuffer, 0, 3); + String headerString = new String(header.array()); + if (!headerString.equals(BAYER_USB_HEADER)) { + throw new IOException("Unexpected header received"); + } + messageSize = responseBuffer[3]; + responseMessage.write(responseBuffer, 4, messageSize); + } else { + Log.w(TAG, "readMessage: got a zero-sized response."); + } + } while (bytesRead > 0 && messageSize == 60); + + String responseString = HexDump.dumpHexString(responseMessage.toByteArray()); + Log.d(TAG, "READ: " + responseString); + + return responseMessage.toByteArray(); + } + + protected void validate() {}; } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java index 0364110375aec3d9c5f6b9c940f500d363758e4f..fc7c4dd6f46e9a8a5788e79c7628027ccde16951 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java @@ -1,12 +1,15 @@ package info.nightscout.android.medtronic.message; +import java.io.IOException; + +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 26/03/2016. */ -public class EndEHSMMessage extends MedtronicSendMessage { - public EndEHSMMessage(MedtronicCnlSession pumpSession) throws EncryptionException { +public class EndEHSMMessage extends MedtronicRequestMessage { + public EndEHSMMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.END_EHSM_SESSION, pumpSession, buildPayload()); } @@ -14,4 +17,9 @@ public class EndEHSMMessage extends MedtronicSendMessage { // Not sure what the payload byte means, but it's the same every time. return new byte[] { 0x01 }; } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicMessage.java index 25588505ab2e817307d0428108a0e2bb98ef4eb7..f0386d7553f5dd1bbf1451f4657de5af4b4cfb43 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicMessage.java @@ -1,7 +1,9 @@ package info.nightscout.android.medtronic.message; +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -29,7 +31,7 @@ public class MedtronicMessage extends ContourNextLinkBinaryMessage { } } - protected MedtronicMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { + protected MedtronicMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { super(commandType, pumpSession, buildPayload(commandAction, payload)); } @@ -93,4 +95,9 @@ public class MedtronicMessage extends ContourNextLinkBinaryMessage { } return decrypted; } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java similarity index 89% rename from app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessage.java rename to app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java index 7bba4ded16da96428fd056f5b985ce821ee9e63e..fb7adb104e540d748aecfaaf5674c286afae6aec 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java @@ -1,14 +1,16 @@ package info.nightscout.android.medtronic.message; +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * Created by lgoedhart on 26/03/2016. */ -public class MedtronicSendMessage extends MedtronicMessage { +public class MedtronicRequestMessage extends MedtronicMessage { static int ENVELOPE_SIZE = 11; static int ENCRYPTED_ENVELOPE_SIZE = 3; static int CRC_SIZE = 2; @@ -28,17 +30,17 @@ public class MedtronicSendMessage extends MedtronicMessage { } } - protected MedtronicSendMessage(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException { + protected MedtronicRequestMessage(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { super(CommandType.SEND_MESSAGE, CommandAction.PUMP_REQUEST, pumpSession, buildPayload(sendMessageType, pumpSession, payload)); } /** - * MedtronicSendMessage: + * MedtronicRequestMessage: * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ * | LE long pumpMAC | byte medtronicSequenceNumber | byte unknown | byte Payload size | byte[] Encrypted Payload bytes | * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ * <p/> - * MedtronicSendMessage (decrypted payload): + * MedtronicRequestMessage (decrypted payload): * +-------------------------+----------------------+----------------------+--------------------+ * | byte sendSequenceNumber | BE short sendMessageType | byte[] Payload bytes | BE short CCITT CRC | * +-------------------------+----------------------+----------------------+--------------------+ @@ -81,4 +83,5 @@ public class MedtronicSendMessage extends MedtronicMessage { return 0x00; } } + } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicReceiveMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicResponseMessage.java similarity index 62% rename from app/src/main/java/info/nightscout/android/medtronic/message/MedtronicReceiveMessage.java rename to app/src/main/java/info/nightscout/android/medtronic/message/MedtronicResponseMessage.java index c2f4a7d58cf10d70925e3d2ab15e3358a4ff3a3f..f70b27c9404089ce5968ecfda756aeabc5752d98 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicReceiveMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicResponseMessage.java @@ -7,13 +7,33 @@ import java.nio.ByteBuffer; /** * Created by lgoedhart on 26/03/2016. */ -public class MedtronicReceiveMessage extends MedtronicMessage { +public class MedtronicResponseMessage extends MedtronicMessage { static int ENVELOPE_SIZE = 22; static int ENCRYPTED_ENVELOPE_SIZE = 3; static int CRC_SIZE = 2; - protected MedtronicReceiveMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { - super(commandType, commandAction, pumpSession, payload); + protected MedtronicResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(CommandType.NO_TYPE, CommandAction.NO_TYPE, pumpSession, payload); + + // TODO - Validate the message, inner CCITT, serial numbers, etc + // If there's not 57 bytes, then we got back a bad message. Not sure how to process these yet. + // Also, READ_INFO and REQUEST_LINK_KEY are not encrypted + if (payload.length >= 57 && + (payload[18] != CommandType.READ_INFO.getValue()) && + (payload[18] != CommandType.REQUEST_LINK_KEY_RESPONSE.getValue())) { + // Replace the encrypted bytes by their decrypted equivalent (same block size) + byte encryptedPayloadSize = payload[56]; + + ByteBuffer encryptedPayload = ByteBuffer.allocate(encryptedPayloadSize); + encryptedPayload.put(payload, 57, encryptedPayloadSize); + byte[] decryptedPayload = decrypt(pumpSession.getKey(), pumpSession.getIV(), encryptedPayload.array()); + + // Now that we have the decrypted payload, rewind the mPayload, and overwrite the bytes + // TODO - because this messes up the existing CCITT, do we want to have a separate buffer for the decrypted payload? + // Should be fine provided we check the CCITT first... + this.mPayload.position(57); + this.mPayload.put(decryptedPayload); + } } public enum ReceiveMessageType { @@ -28,20 +48,24 @@ public class MedtronicReceiveMessage extends MedtronicMessage { } /** - * MedtronicReceiveMessage: + * MedtronicResponseMessage: * +------------------+-----------------+-----------------+---------------------------------+-------------------+--------------------------------+ * | LE short unknown | LE long pumpMAC | LE long linkMAC | byte[3] responseSequenceNumber? | byte Payload size | byte[] Encrypted Payload bytes | * +------------------+-----------------+-----------------+---------------------------------+-------------------+--------------------------------+ * <p/> - * MedtronicReceiveMessage (decrypted payload): + * MedtronicResponseMessage (decrypted payload): * +----------------------------+-----------------------------+----------------------+--------------------+ * | byte receiveSequenceNumber | BE short receiveMessageType | byte[] Payload bytes | BE short CCITT CRC | * +----------------------------+-----------------------------+----------------------+--------------------+ */ public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException { // TODO - turn this into a factory + + return new MedtronicResponseMessage(pumpSession, bytes); + /* ContourNextLinkMessage message = MedtronicMessage.fromBytes(bytes); + // TODO - Validate the message, inner CCITT, serial numbers, etc // If there's not 57 bytes, then we got back a bad message. Not sure how to process these yet. @@ -62,6 +86,7 @@ public class MedtronicReceiveMessage extends MedtronicMessage { message.mPayload.position(57); message.mPayload.put(decryptedPayload); } - return message; + return message;*/ } + } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java index d31eb36a229654efedd6b9849fac749c1b748254..a00715319d580be7e5ab90d8cb00af3ccc2ba802 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java @@ -1,12 +1,20 @@ package info.nightscout.android.medtronic.message; +import java.io.IOException; + +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 26/03/2016. */ -public class PumpBasalPatternRequestMessage extends MedtronicSendMessage { - public PumpBasalPatternRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException { +public class PumpBasalPatternRequestMessage extends MedtronicRequestMessage { + public PumpBasalPatternRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.READ_BASAL_PATTERN_REQUEST, pumpSession, null); } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternResponseMessage.java index d4b4ef97d55422a5d5be2a5179879569a59cfcad..43132b661edfbcb0e2e3f2d66c5b39147cdb5646 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternResponseMessage.java @@ -5,14 +5,14 @@ import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 27/03/2016. */ -public class PumpBasalPatternResponseMessage extends MedtronicReceiveMessage { - protected PumpBasalPatternResponseMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { - super(commandType, commandAction, pumpSession, payload); +public class PumpBasalPatternResponseMessage extends MedtronicResponseMessage { + protected PumpBasalPatternResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(pumpSession, payload); } public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException { // TODO - turn this into a factory - ContourNextLinkMessage message = MedtronicReceiveMessage.fromBytes(pumpSession, bytes); + ContourNextLinkMessage message = MedtronicResponseMessage.fromBytes(pumpSession, bytes); // TODO - Validate the MessageType 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 1162bfe139ca65e06fe1eb95571f1ff67520f78c..0c507a6ae06e91133a3188896ed8e41aa46be7fd 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 @@ -1,12 +1,20 @@ package info.nightscout.android.medtronic.message; +import java.io.IOException; + +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 26/03/2016. */ -public class PumpStatusRequestMessage extends MedtronicSendMessage { - public PumpStatusRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException { +public class PumpStatusRequestMessage extends MedtronicRequestMessage { + public PumpStatusRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.READ_PUMP_STATUS_REQUEST, pumpSession, null); } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java index 06e9a0f3357d2456f64a5eb7c84ac3218d1e35ee..151348e08ba528e1a0fcbe751db5bbcf81d8e39e 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java @@ -5,14 +5,14 @@ import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 27/03/2016. */ -public class PumpStatusResponseMessage extends MedtronicReceiveMessage { - protected PumpStatusResponseMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { - super(commandType, commandAction, pumpSession, payload); +public class PumpStatusResponseMessage extends MedtronicResponseMessage { + protected PumpStatusResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(pumpSession, payload); } public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException { // TODO - turn this into a factory - ContourNextLinkMessage message = MedtronicReceiveMessage.fromBytes(pumpSession, bytes); + ContourNextLinkMessage message = MedtronicResponseMessage.fromBytes(pumpSession, bytes); // TODO - Validate the MessageType 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 89305b0a9b3873d3ec4079eeacebf8d740443ffe..c773fa1034cacad0cd1fc3ff355f5969a0e88aae 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 @@ -1,12 +1,20 @@ package info.nightscout.android.medtronic.message; +import java.io.IOException; + +import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 26/03/2016. */ -public class PumpTimeRequestMessage extends MedtronicSendMessage { - public PumpTimeRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException { +public class PumpTimeRequestMessage extends MedtronicRequestMessage { + public PumpTimeRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.TIME_REQUEST, pumpSession, null); } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } } 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 3437dd69c65e9adfe188966ea14cbc1a6f8afb18..6f1ca90a46d23986267e29670a2d805bc7dd981e 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 @@ -5,14 +5,14 @@ import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 27/03/2016. */ -public class PumpTimeResponseMessage extends MedtronicReceiveMessage { - protected PumpTimeResponseMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { - super(commandType, commandAction, pumpSession, payload); +public class PumpTimeResponseMessage extends MedtronicResponseMessage { + protected PumpTimeResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(pumpSession, payload); } public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException { // TODO - turn this into a factory - ContourNextLinkMessage message = MedtronicReceiveMessage.fromBytes(pumpSession, bytes); + ContourNextLinkMessage message = MedtronicResponseMessage.fromBytes(pumpSession, bytes); // TODO - Validate the MessageType diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..770a6d2ce0bb37599619c61d424995e29ae08361 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java @@ -0,0 +1,28 @@ +package info.nightscout.android.medtronic.message; + +import java.io.IOException; + +import info.nightscout.android.USB.UsbHidDriver; +import info.nightscout.android.medtronic.MedtronicCnlSession; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.concurrent.TimeoutException; + +/** + * Created by volker on 10.12.2016. + */ + +public class ReadInfoRequestMessage extends ContourNextLinkBinaryMessage { + public ReadInfoRequestMessage(MedtronicCnlSession pumpSession) throws ChecksumException { + super(ContourNextLinkBinaryMessage.CommandType.READ_INFO, pumpSession, null); + } + + public ReadInfoResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException { + sendMessage(mDevice); + + ReadInfoResponseMessage response = new ReadInfoResponseMessage(mPumpSession, readMessage(mDevice)); + + return response; + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java index 68aab2df7977d4235e1c445b4b8ac0692d16e88b..87eaf9f20fd82c03383a8f7408a03fa794d7bfb2 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java @@ -1,21 +1,36 @@ package info.nightscout.android.medtronic.message; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 10/05/2016. */ -public class ReadInfoResponseMessage extends MedtronicReceiveMessage { - protected ReadInfoResponseMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { - super(commandType, commandAction, pumpSession, payload); +public class ReadInfoResponseMessage extends MedtronicResponseMessage { + private long linkMAC; + private long pumpMAC; + + protected ReadInfoResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException, EncryptionException { + super(pumpSession, payload); + + ByteBuffer infoBuffer = ByteBuffer.allocate(16); + infoBuffer.order(ByteOrder.BIG_ENDIAN); + infoBuffer.put(this.encode(), 0x21, 16); + linkMAC = infoBuffer.getLong(0); + pumpMAC = infoBuffer.getLong(8); } public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException { - // TODO - turn this into a factory - ContourNextLinkMessage message = MedtronicReceiveMessage.fromBytes(pumpSession, bytes); + return new ReadInfoResponseMessage(pumpSession, bytes); + } - // TODO - Validate the MessageType + public long getLinkMAC() { + return linkMAC; + } - return message; + public long getPumpMAC() { + return pumpMAC; } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java index 423e40fb8ab61296fc9c26995837a56932715a7e..08aa3a33826648fb99675162891b520b898802a5 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java @@ -5,14 +5,14 @@ import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by lgoedhart on 10/05/2016. */ -public class RequestLinkKeyResponseMessage extends MedtronicReceiveMessage { - protected RequestLinkKeyResponseMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) { - super(commandType, commandAction, pumpSession, payload); +public class RequestLinkKeyResponseMessage extends MedtronicResponseMessage { + protected RequestLinkKeyResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(pumpSession, payload); } public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException { // TODO - turn this into a factory - ContourNextLinkMessage message = MedtronicReceiveMessage.fromBytes(pumpSession, bytes); + ContourNextLinkMessage message = MedtronicResponseMessage.fromBytes(pumpSession, bytes); // TODO - Validate the MessageType