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 db32bac435844e3cb586cee8d192c8ee824f335e..544caaf5098ec6b5f46f5303099b2cc92b026297 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 @@ -1,14 +1,14 @@ package info.nightscout.android.medtronic.message; -import info.nightscout.android.medtronic.MedtronicCnlSession; - import java.nio.ByteBuffer; import java.nio.ByteOrder; +import info.nightscout.android.medtronic.MedtronicCnlSession; + /** * Created by lgoedhart on 26/03/2016. */ -public class ChannelNegotiateMessage extends MedtronicMessage { +public class ChannelNegotiateMessage extends MedtronicRequestMessage { 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/CloseConnectionRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..a822ce73d09ea7eeac055c90b1da3af798d118be --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java @@ -0,0 +1,26 @@ +package info.nightscout.android.medtronic.message; + +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 CloseConnectionRequestMessage extends ContourNextLinkBinaryRequestMessage { + public CloseConnectionRequestMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { + super(CommandType.CLOSE_CONNECTION, pumpSession, payload); + } + + public OpenConnectionResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException { + sendMessage(mDevice); + + OpenConnectionResponseMessage response = new OpenConnectionResponseMessage(mPumpSession, readMessage(mDevice)); + + // FIXME - We need to care what the response message is - wrong MAC and all that + return response; + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..03a9eb7414ff09584c7ad4b89c8c4f96ec9d3263 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java @@ -0,0 +1,13 @@ +package info.nightscout.android.medtronic.message; + +import info.nightscout.android.medtronic.MedtronicCnlSession; + +/** + * Created by lgoedhart on 10/05/2016. + */ +public class CloseConnectionResponseMessage extends MedtronicResponseMessage { + protected CloseConnectionResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException, EncryptionException { + super(pumpSession, payload); + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java similarity index 69% rename from app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java rename to app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java index b31d451dc20c0d42ab10024ca4ed18a78473b953..24238af71c62fcb961b147a8c1dd4fe7ac2789ee 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java @@ -1,28 +1,30 @@ 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; 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 ContourNextLinkBinaryMessage extends ContourNextLinkMessage { +public class ContourNextLinkBinaryRequestMessage extends ContourNextLinkRequestMessage { + private final static int ENVELOPE_SIZE = 33; + //protected ByteBuffer mBayerEnvelope; //protected ByteBuffer mBayerPayload; protected CommandType mCommandType = CommandType.NO_TYPE; + protected MedtronicCnlSession mPumpSession; - private final static int ENVELOPE_SIZE = 33; + public ContourNextLinkBinaryRequestMessage(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { + super(buildPayload(commandType, pumpSession, payload)); - public ContourNextLinkBinaryMessage(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { - super(pumpSession, buildPayload(commandType, pumpSession, payload)); - mCommandType = commandType; - mPumpSession = pumpSession; + this.mPumpSession = pumpSession; + this.mCommandType = commandType; // Validate checksum byte messageChecksum = this.mPayload.get(32); @@ -33,14 +35,6 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { } } - public static ContourNextLinkMessage fromBytes(byte[] bytes) throws ChecksumException { - ContourNextLinkMessage message = new ContourNextLinkMessage(bytes); - message.validate(); - - return message; - } - - /** * Handle incrementing sequence number * @@ -81,14 +75,4 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage { return payloadBuffer.array(); } - protected void validate(ContourNextLinkMessage message) throws ChecksumException { - // Validate checksum - byte messageChecksum = message.mPayload.get(32); - byte calculatedChecksum = (byte) (MessageUtils.oneByteSum(message.mPayload.array()) - messageChecksum); - - if (messageChecksum != calculatedChecksum) { - throw new ChecksumException(String.format(Locale.getDefault(), "Expected to get %d. Got %d", (int) calculatedChecksum, (int) messageChecksum)); - } - } - } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..549ee889560c0c04b62bf54824b202501f70f672 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryResponseMessage.java @@ -0,0 +1,15 @@ +package info.nightscout.android.medtronic.message; + +import java.io.IOException; +import java.util.Locale; +import java.util.concurrent.TimeoutException; + +/** + * Created by lgoedhart on 26/03/2016. + */ +public class ContourNextLinkBinaryResponseMessage extends ContourNextLinkResponseMessage { + + public ContourNextLinkBinaryResponseMessage(byte[] payload) throws ChecksumException { + super(payload); + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java index 151fe484262a1173de154a8a7308433f12a1e248..9839f752f66b52f66837536f6928a1248d5077e2 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java @@ -4,13 +4,14 @@ import java.io.IOException; 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 ContourNextLinkCommandMessage extends ContourNextLinkMessage { +public class ContourNextLinkCommandMessage extends ContourNextLinkRequestMessage { public ContourNextLinkCommandMessage(ASCII command) { - super(new byte[]{command.value}); + super(new byte[]{command.getValue()}); } public ContourNextLinkCommandMessage(byte command) { @@ -21,11 +22,13 @@ public class ContourNextLinkCommandMessage extends ContourNextLinkMessage { super(command.getBytes()); } - public ContourNextLinkCommandResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException, UnexpectedMessageException { + + public ContourNextLinkCommandResponse send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException { sendMessage(mDevice); - ContourNextLinkCommandResponseMessage response = new ContourNextLinkCommandResponseMessage(mPumpSession, readMessage(mDevice));; + ContourNextLinkCommandResponse response = new ContourNextLinkCommandResponse(readMessage(mDevice)); + // FIXME - We need to care what the response message is - wrong MAC and all that return response; } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponse.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..12f9b9575057a497020176d2f00254cc9a934faf --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponse.java @@ -0,0 +1,13 @@ +package info.nightscout.android.medtronic.message; + +import info.nightscout.android.medtronic.MedtronicCnlSession; + +/** + * Created by volker on 10.12.2016. + */ +public class ContourNextLinkCommandResponse extends ContourNextLinkBinaryResponseMessage { + + public ContourNextLinkCommandResponse(byte[] payload) throws ChecksumException { + super(payload); + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponseMessage.java deleted file mode 100644 index f5bde36799dda28dfcc2ffbd84d9324e168d806a..0000000000000000000000000000000000000000 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponseMessage.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.android.medtronic.message; - -import info.nightscout.android.medtronic.MedtronicCnlSession; - -/** - * Created by volker on 10.12.2016. - */ -public class ContourNextLinkCommandResponseMessage extends ContourNextLinkBinaryMessage { - - public ContourNextLinkCommandResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { - super(CommandType.NO_TYPE, pumpSession, payload); - } -} 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 168e93122c4dcf54b88de82533d43d659b915408..36d39a48205ed0a53d047efc1b91879539320121 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 @@ -25,15 +25,6 @@ public class ContourNextLinkMessage { private static final String BAYER_USB_HEADER = "ABC"; protected ByteBuffer mPayload; - protected MedtronicCnlSession mPumpSession; - - 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), @@ -47,15 +38,16 @@ public class ContourNextLinkMessage { value = (byte) commandAction; } - public final byte getValue() { + public byte getValue() { return value; } - public final boolean equals(byte value) { + public boolean equals(byte value) { return this.value == value; } } + public enum CommandType { NO_TYPE(0x0), OPEN_CONNECTION(0x10), @@ -74,17 +66,16 @@ public class ContourNextLinkMessage { value = (byte) commandType; } - public final byte getValue() { + public byte getValue() { return value; } - public final boolean equals(byte value) { + public boolean equals(byte value) { return this.value == value; } } - protected ContourNextLinkMessage(MedtronicCnlSession pumpSession, byte[] bytes) { - this.mPumpSession = pumpSession; + protected ContourNextLinkMessage(byte[] bytes) { setPayload(bytes); } @@ -106,10 +97,6 @@ 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(); @@ -162,9 +149,6 @@ public class ContourNextLinkMessage { return responseMessage.toByteArray(); } - protected void validate() {}; - - public enum ASCII { STX(0x02), EOT(0x04), @@ -178,6 +162,10 @@ public class ContourNextLinkMessage { this.value = (byte) code; } + public byte getValue() { + return value; + } + public boolean equals(byte value) { return this.value == value; } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..390380d6b4d5bb88a4683a2c98e35d049ef71b95 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java @@ -0,0 +1,20 @@ +package info.nightscout.android.medtronic.message; + + +import java.io.IOException; +import java.util.Locale; +import java.util.concurrent.TimeoutException; + +import info.nightscout.android.medtronic.MedtronicCnlSession; +import info.nightscout.android.medtronic.message.ContourNextLinkMessage; +import info.nightscout.android.medtronic.message.UnexpectedMessageException; + +/** + * Created by volker on 12.12.2016. + */ + +public class ContourNextLinkRequestMessage extends ContourNextLinkMessage { + protected ContourNextLinkRequestMessage(byte[] bytes) { + super(bytes); + } +} 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 index a2f913d2496ec331021bb537e165cab0ed7769f4..24d6aa8b59000418060a7d4f44e30b2637716d92 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java @@ -8,16 +8,28 @@ import java.util.concurrent.TimeoutException; import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; +import info.nightscout.android.medtronic.message.ChecksumException; +import info.nightscout.android.medtronic.message.ContourNextLinkMessage; +import info.nightscout.android.medtronic.message.UnexpectedMessageException; /** * 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; + public ContourNextLinkResponseMessage(byte[] payload) throws ChecksumException { + super(payload); + } + + public void checkControlMessage(ASCII controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException { + checkControlMessage(mPayload.array(), controlCharacter); } + public void checkControlMessage(byte[] msg, ASCII controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException { + if (msg.length != 1 || !controlCharacter.equals(msg[0])) { + throw new UnexpectedMessageException(String.format(Locale.getDefault(), "Expected to get control character '%d' Got '%d'.", + (int) controlCharacter.getValue(), (int) msg[0])); + } + } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoResponseCommandMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoResponseCommandMessage.java index fec7c00038cfa9368ee6340ecff94ce5e5bf7311..1400a2699299fd903315fbff494cbbf41f0d8aca 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoResponseCommandMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoResponseCommandMessage.java @@ -6,6 +6,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import info.nightscout.android.medtronic.MedtronicCnlSession; +import info.nightscout.android.medtronic.message.ChecksumException; +import info.nightscout.android.medtronic.message.EncryptionException; +import info.nightscout.android.medtronic.message.MedtronicResponseMessage; +import info.nightscout.android.medtronic.message.UnexpectedMessageException; /** * Created by lgoedhart on 10/05/2016. 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 deleted file mode 100644 index 86eef799cc488c9c84fbe2f5f8a967824821fa49..0000000000000000000000000000000000000000 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicMessage.java +++ /dev/null @@ -1,76 +0,0 @@ -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 javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -/** - * Created by lgoedhart on 26/03/2016. - */ -public class MedtronicMessage extends ContourNextLinkBinaryMessage { - static int ENVELOPE_SIZE = 2; - static int CRC_SIZE = 2; - - - protected MedtronicMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { - super(commandType, pumpSession, buildPayload(commandAction, payload)); - } - - /** - * MedtronicMessage: - * +---------------+-------------------+----------------------+--------------------+ - * | CommandAction | byte Payload Size | byte[] Payload bytes | LE short CCITT CRC | - * +---------------+-------------------+----------------------+--------------------+ - */ - protected static byte[] buildPayload(CommandAction commandAction, byte[] payload) { - byte payloadLength = (byte) (payload == null ? 0 : payload.length); - - ByteBuffer payloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + payloadLength + CRC_SIZE); - payloadBuffer.order(ByteOrder.LITTLE_ENDIAN); - - payloadBuffer.put(commandAction.getValue()); - payloadBuffer.put((byte) (ENVELOPE_SIZE + payloadLength)); - if (payloadLength != 0) { - payloadBuffer.put(payload != null ? payload : new byte[0]); - } - - payloadBuffer.putShort((short) MessageUtils.CRC16CCITT(payloadBuffer.array(), 0xffff, 0x1021, ENVELOPE_SIZE + payloadLength)); - - return payloadBuffer.array(); - } - - public static ContourNextLinkMessage fromBytes(byte[] bytes) throws ChecksumException { - ContourNextLinkMessage message = ContourNextLinkBinaryMessage.fromBytes(bytes); - - // TODO - Validate the CCITT - return message; - } - - // TODO - maybe move the SecretKeySpec, IvParameterSpec and Cipher construction into the PumpSession? - protected static byte[] encrypt(byte[] key, byte[] iv, byte[] clear) throws EncryptionException { - SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - byte[] encrypted = new byte[0]; - - try { - Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); - encrypted = cipher.doFinal(clear); - } catch (Exception e) { - throw new EncryptionException( "Could not encrypt Medtronic Message" ); - } - return encrypted; - } - - protected void sendMessage(UsbHidDriver mDevice) throws IOException { - super.sendMessage(mDevice); - mPumpSession.incrMedtronicSequenceNumber(); - } -} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicPumpMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicPumpMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..87c6db3162b2dea37daa3f472e2456b735060d17 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicPumpMessage.java @@ -0,0 +1,15 @@ +package info.nightscout.android.medtronic.message; + +import info.nightscout.android.medtronic.MedtronicCnlSession; + +/** + * Created by volker on 15.12.2016. + */ + +public class MedtronicPumpMessage extends ContourNextLinkMessage { + + protected MedtronicPumpMessage(MedtronicCnlSession pumpSession, byte[] bytes) { + super(bytes); + + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java index fb7adb104e540d748aecfaaf5674c286afae6aec..ff0185a26f0e2555246a9723e04c8198992ae832 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicRequestMessage.java @@ -1,20 +1,32 @@ 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 javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import info.nightscout.android.USB.UsbHidDriver; +import info.nightscout.android.medtronic.MedtronicCnlSession; + /** * Created by lgoedhart on 26/03/2016. */ -public class MedtronicRequestMessage extends MedtronicMessage { +public class MedtronicRequestMessage extends ContourNextLinkBinaryRequestMessage { static int ENVELOPE_SIZE = 11; static int ENCRYPTED_ENVELOPE_SIZE = 3; static int CRC_SIZE = 2; + protected MedtronicRequestMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { + super(commandType, pumpSession, buildPayload(commandAction, payload)); + } + + protected MedtronicRequestMessage(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + this(CommandType.SEND_MESSAGE, CommandAction.PUMP_REQUEST, pumpSession, buildPayload(sendMessageType, pumpSession, payload)); + } + public enum SendMessageType { NO_TYPE(0x0), BEGIN_EHSM_SESSION(0x412), @@ -28,19 +40,47 @@ public class MedtronicRequestMessage extends MedtronicMessage { SendMessageType(int messageType) { value = (short) messageType; } + + public short getValue() { + return value; + } + + public boolean equals(short value) { + return this.value == value; + } } - protected MedtronicRequestMessage(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { - super(CommandType.SEND_MESSAGE, CommandAction.PUMP_REQUEST, pumpSession, buildPayload(sendMessageType, pumpSession, payload)); + /** + * MedtronicMessage: + * +---------------+-------------------+----------------------+--------------------+ + * | CommandAction | byte Payload Size | byte[] Payload bytes | LE short CCITT CRC | + * +---------------+-------------------+----------------------+--------------------+ + */ + protected static byte[] buildPayload(CommandAction commandAction, byte[] payload) { + byte payloadLength = (byte) (payload == null ? 0 : payload.length); + + ByteBuffer payloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + payloadLength + CRC_SIZE); + payloadBuffer.order(ByteOrder.LITTLE_ENDIAN); + + payloadBuffer.put(commandAction.getValue()); + payloadBuffer.put((byte) (ENVELOPE_SIZE + payloadLength)); + if (payloadLength != 0) { + payloadBuffer.put(payload != null ? payload : new byte[0]); + } + + payloadBuffer.putShort((short) MessageUtils.CRC16CCITT(payloadBuffer.array(), 0xffff, 0x1021, ENVELOPE_SIZE + payloadLength)); + + return payloadBuffer.array(); } + /** - * MedtronicRequestMessage: + * MedtronicSendMessage: * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ * | LE long pumpMAC | byte medtronicSequenceNumber | byte unknown | byte Payload size | byte[] Encrypted Payload bytes | * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ * <p/> - * MedtronicRequestMessage (decrypted payload): + * MedtronicSendMessage (decrypted payload): * +-------------------------+----------------------+----------------------+--------------------+ * | byte sendSequenceNumber | BE short sendMessageType | byte[] Payload bytes | BE short CCITT CRC | * +-------------------------+----------------------+----------------------+--------------------+ @@ -71,6 +111,27 @@ public class MedtronicRequestMessage extends MedtronicMessage { return payloadBuffer.array(); } + // TODO - maybe move the SecretKeySpec, IvParameterSpec and Cipher construction into the PumpSession? + protected static byte[] encrypt(byte[] key, byte[] iv, byte[] clear) throws EncryptionException { + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + byte[] encrypted = new byte[0]; + + try { + Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); + encrypted = cipher.doFinal(clear); + } catch (Exception e) { + throw new EncryptionException( "Could not encrypt Medtronic Message" ); + } + return encrypted; + } + + protected void sendMessage(UsbHidDriver mDevice) throws IOException { + super.sendMessage(mDevice); + mPumpSession.incrMedtronicSequenceNumber(); + } + protected static byte sendSequenceNumber(SendMessageType sendMessageType) { switch (sendMessageType) { case BEGIN_EHSM_SESSION: 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 c7d51ff063409166ecaaad724ff05d78a4c3cb98..8557561507042e5a23c857a9c5bca483334d7472 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 @@ -17,7 +17,7 @@ public class MedtronicResponseMessage extends ContourNextLinkResponseMessage { static int CRC_SIZE = 2; protected MedtronicResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { - super(pumpSession, payload); + super(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. diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..3a5ea5fcfca6825abe6f488cab4bc4a6aa5318da --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java @@ -0,0 +1,26 @@ +package info.nightscout.android.medtronic.message; + +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 OpenConnectionRequestMessage extends ContourNextLinkBinaryRequestMessage { + public OpenConnectionRequestMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException { + super(CommandType.OPEN_CONNECTION, pumpSession, payload); + } + + public OpenConnectionResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException { + sendMessage(mDevice); + + OpenConnectionResponseMessage response = new OpenConnectionResponseMessage(mPumpSession, readMessage(mDevice)); + + // FIXME - We need to care what the response message is - wrong MAC and all that + return response; + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..38f4ffb75dd967fff04f05782ea22d428540510f --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java @@ -0,0 +1,16 @@ +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 OpenConnectionResponseMessage extends MedtronicResponseMessage { + protected OpenConnectionResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException, EncryptionException { + super(pumpSession, payload); + } + +} \ No newline at end of file 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 index 770a6d2ce0bb37599619c61d424995e29ae08361..dc2a97bc5538016a753e646acce0499fb04f36db 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java @@ -5,17 +5,15 @@ 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 class ReadInfoRequestMessage extends ContourNextLinkBinaryRequestMessage { public ReadInfoRequestMessage(MedtronicCnlSession pumpSession) throws ChecksumException { - super(ContourNextLinkBinaryMessage.CommandType.READ_INFO, pumpSession, null); + super(ContourNextLinkBinaryRequestMessage.CommandType.READ_INFO, pumpSession, null); } public ReadInfoResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException { diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java index fd4e16ea399f271ce7bc18b2d1ac97857650f0dc..ea4a446d6de411845db4d8610b13144da81be4a2 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java @@ -10,7 +10,7 @@ import info.nightscout.android.medtronic.MedtronicCnlSession; * Created by volker on 10.12.2016. */ -public class RequestLinkKeyRequestMessage extends ContourNextLinkBinaryMessage { +public class RequestLinkKeyRequestMessage extends ContourNextLinkBinaryRequestMessage { public RequestLinkKeyRequestMessage(MedtronicCnlSession pumpSession) throws ChecksumException { super(CommandType.REQUEST_LINK_KEY, pumpSession, null); }