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 1cb46a5e4d825e8a38e20e9c9cdd60703a4a1d10..766a8a6145fd6a2bea03d1ef6d7146fdf97b951e 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java @@ -166,7 +166,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler { public void requestDeviceInfo() throws IOException, TimeoutException, UnexpectedMessageException, ChecksumException, EncryptionException { - DeviceInfoResponseCommandMessage response = new DeviceInfoRequestCommandMessage().send(mDevice); + DeviceInfoResponseCommandMessage response = new DeviceInfoRequestCommandMessage(mPumpSession).send(mDevice); //TODO - extract more details form the device info. mStickSerial = response.getSerial(); 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 b7dd2ffe786ba38c9274e800df67a954f2d850d7..b31d451dc20c0d42ab10024ca4ed18a78473b953 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 @@ -19,31 +19,8 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { private final static int ENVELOPE_SIZE = 33; - public enum CommandType { - NO_TYPE(0x0), - OPEN_CONNECTION(0x10), - CLOSE_CONNECTION(0x11), - SEND_MESSAGE(0x12), - READ_INFO(0x14), - REQUEST_LINK_KEY(0x16), - SEND_LINK_KEY(0x17), - RECEIVE_MESSAGE(0x80), - SEND_MESSAGE_RESPONSE(0x81), - REQUEST_LINK_KEY_RESPONSE(0x86); - - private byte value; - - CommandType(int commandType) { - value = (byte) commandType; - } - - public int getValue() { - return value; - } - } - public ContourNextLinkBinaryMessage(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { - super(buildPayload(commandType, pumpSession, payload)); + super(pumpSession, buildPayload(commandType, pumpSession, payload)); mCommandType = commandType; mPumpSession = pumpSession; @@ -64,11 +41,6 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { } - public void checkControlMessage(ASCII controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException { - checkControlMessage(mPayload.array(), controlCharacter); - } - - /** * Handle incrementing sequence number * @@ -91,7 +63,7 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { payloadBuffer.put("000000".getBytes()); // Text of PumpInfo serial, but 000000 for 640g byte[] unknownBytes = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; payloadBuffer.put(unknownBytes); - payloadBuffer.put(commandType.value); + payloadBuffer.put(commandType.getValue()); payloadBuffer.putInt(pumpSession.getBayerSequenceNumber()); byte[] unknownBytes2 = {0, 0, 0, 0, 0}; payloadBuffer.put(unknownBytes2); @@ -119,11 +91,4 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { } } - protected void checkControlMessage(byte[] msg, ASCII controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException { - if (msg.length != 1 || msg[0] != controlCharacter.value) { - throw new UnexpectedMessageException(String.format(Locale.getDefault(), "Expected to get control character '%d' Got '%d'.", - (int) controlCharacter.value, (int) msg[0])); - } - } - } 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 6aab87424b5fa1d5c311bcaf85f38d6b4040b75f..168e93122c4dcf54b88de82533d43d659b915408 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 @@ -5,6 +5,7 @@ import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Locale; import java.util.concurrent.TimeoutException; import info.nightscout.android.USB.UsbHidDriver; @@ -26,7 +27,64 @@ public class ContourNextLinkMessage { protected ByteBuffer mPayload; protected MedtronicCnlSession mPumpSession; - protected ContourNextLinkMessage(byte[] bytes) { + protected void checkControlMessage(byte[] msg, ASCII controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException { + if (msg.length != 1 || msg[0] != controlCharacter.value) { + throw new UnexpectedMessageException(String.format(Locale.getDefault(), "Expected to get control character '%d' Got '%d'.", + (int) controlCharacter.value, (int) msg[0])); + } + } + + + public enum CommandAction { + NO_TYPE(0x0), + CHANNEL_NEGOTIATE(0x03), + PUMP_REQUEST(0x05), + PUMP_RESPONSE(0x55); + + private byte value; + + CommandAction(int commandAction) { + value = (byte) commandAction; + } + + public final byte getValue() { + return value; + } + + public final boolean equals(byte value) { + return this.value == value; + } + } + + public enum CommandType { + NO_TYPE(0x0), + OPEN_CONNECTION(0x10), + CLOSE_CONNECTION(0x11), + SEND_MESSAGE(0x12), + READ_INFO(0x14), + REQUEST_LINK_KEY(0x16), + SEND_LINK_KEY(0x17), + RECEIVE_MESSAGE(0x80), + SEND_MESSAGE_RESPONSE(0x81), + REQUEST_LINK_KEY_RESPONSE(0x86); + + private byte value; + + CommandType(int commandType) { + value = (byte) commandType; + } + + public final byte getValue() { + return value; + } + + public final boolean equals(byte value) { + return this.value == value; + } + } + + protected ContourNextLinkMessage(MedtronicCnlSession pumpSession, byte[] bytes) { + this.mPumpSession = pumpSession; setPayload(bytes); } @@ -48,6 +106,10 @@ public class ContourNextLinkMessage { } } + public void checkControlMessage(ASCII controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException { + checkControlMessage(mPayload.array(), controlCharacter); + } + protected void sendMessage(UsbHidDriver mDevice) throws IOException { int pos = 0; byte[] message = this.encode(); diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..a2f913d2496ec331021bb537e165cab0ed7769f4 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java @@ -0,0 +1,23 @@ +package info.nightscout.android.medtronic.message; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Locale; +import java.util.concurrent.TimeoutException; + +import info.nightscout.android.USB.UsbHidDriver; +import info.nightscout.android.medtronic.MedtronicCnlSession; + +/** + * Created by lgoedhart on 26/03/2016. + */ +public class ContourNextLinkResponseMessage extends ContourNextLinkMessage { + + public ContourNextLinkResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { + super(pumpSession, payload); + mPumpSession = pumpSession; + + } + +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java index e92a185568fcacdda88640c8573c3ebd52cec444..3dc9eb0265fb936f2f293445e15826167b985723 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java @@ -4,14 +4,15 @@ import java.io.IOException; import java.util.concurrent.TimeoutException; import info.nightscout.android.USB.UsbHidDriver; +import info.nightscout.android.medtronic.MedtronicCnlSession; /** * Created by volker on 10.12.2016. */ public class DeviceInfoRequestCommandMessage extends ContourNextLinkMessage { - public DeviceInfoRequestCommandMessage() { - super("X".getBytes()); + public DeviceInfoRequestCommandMessage(MedtronicCnlSession pumpSession) { + super(pumpSession, "X".getBytes()); } public DeviceInfoResponseCommandMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException, UnexpectedMessageException { 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 f0386d7553f5dd1bbf1451f4657de5af4b4cfb43..86eef799cc488c9c84fbe2f5f8a967824821fa49 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 @@ -18,21 +18,9 @@ public class MedtronicMessage extends ContourNextLinkBinaryMessage { static int ENVELOPE_SIZE = 2; static int CRC_SIZE = 2; - public enum CommandAction { - NO_TYPE(0x0), - CHANNEL_NEGOTIATE(0x03), - PUMP_REQUEST(0x05), - PUMP_RESPONSE(0x55); - - private byte value; - - CommandAction(int commandAction) { - value = (byte) commandAction; - } - } protected MedtronicMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { - super(commandType, pumpSession, buildPayload(commandAction, payload)); + super(commandType, pumpSession, buildPayload(commandAction, payload)); } /** @@ -47,7 +35,7 @@ public class MedtronicMessage extends ContourNextLinkBinaryMessage { ByteBuffer payloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + payloadLength + CRC_SIZE); payloadBuffer.order(ByteOrder.LITTLE_ENDIAN); - payloadBuffer.put(commandAction.value); + payloadBuffer.put(commandAction.getValue()); payloadBuffer.put((byte) (ENVELOPE_SIZE + payloadLength)); if (payloadLength != 0) { payloadBuffer.put(payload != null ? payload : new byte[0]); @@ -81,21 +69,6 @@ public class MedtronicMessage extends ContourNextLinkBinaryMessage { return encrypted; } - protected static byte[] decrypt(byte[] key, byte[] iv, byte[] encrypted) throws EncryptionException { - SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - byte[] decrypted; - - try { - Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); - cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); - decrypted = cipher.doFinal(encrypted); - } catch (Exception e ) { - throw new EncryptionException( "Could not decrypt Medtronic Message" ); - } - 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/MedtronicResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicResponseMessage.java index f70b27c9404089ce5968ecfda756aeabc5752d98..c7d51ff063409166ecaaad724ff05d78a4c3cb98 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicResponseMessage.java @@ -4,16 +4,20 @@ import info.nightscout.android.medtronic.MedtronicCnlSession; import java.nio.ByteBuffer; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + /** * Created by lgoedhart on 26/03/2016. */ -public class MedtronicResponseMessage extends MedtronicMessage { +public class MedtronicResponseMessage extends ContourNextLinkResponseMessage { static int ENVELOPE_SIZE = 22; static int ENCRYPTED_ENVELOPE_SIZE = 3; static int CRC_SIZE = 2; protected MedtronicResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { - super(CommandType.NO_TYPE, CommandAction.NO_TYPE, pumpSession, payload); + super(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. @@ -89,4 +93,18 @@ public class MedtronicResponseMessage extends MedtronicMessage { return message;*/ } + protected static byte[] decrypt(byte[] key, byte[] iv, byte[] encrypted) throws EncryptionException { + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + byte[] decrypted; + + try { + Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); + decrypted = cipher.doFinal(encrypted); + } catch (Exception e ) { + throw new EncryptionException( "Could not decrypt Medtronic Message" ); + } + return decrypted; + } }