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 0f3abf2f8f8278a0b545e81a1369b3be9bf65819..6bea733aa62958af1e2db2d02ef51f3262bf001d 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java @@ -152,8 +152,6 @@ public class MedtronicCnlReader { if (response.getRadioChannel() == mPumpSession.getRadioChannel()) { break; - } else { - throw new IOException(String.format(Locale.getDefault(), "Expected to get a message for channel %d. Got %d", mPumpSession.getRadioChannel(), response.getRadioChannel())); } } 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 60f9f5f073cb30ae6bf5e7d7cbc599024a05c330..dce2a91254a28f3ebcd1bd5b89e001b16b409cf1 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 @@ -11,7 +11,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 26/03/2016. */ -public class BeginEHSMMessage extends MedtronicRequestMessage { +public class BeginEHSMMessage extends MedtronicSendMessageRequestMessage { public BeginEHSMMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.BEGIN_EHSM_SESSION, pumpSession, buildPayload()); } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateResponseMessage.java index 63d6fe6dff7b449b7b03867828f0cc62c384abb2..67f8d9beba4495cc760b07748f9141a576b66ee5 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateResponseMessage.java @@ -2,6 +2,9 @@ package info.nightscout.android.medtronic.message; import android.util.Log; +import java.io.IOException; +import java.util.Locale; + import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; @@ -14,7 +17,7 @@ public class ChannelNegotiateResponseMessage extends ContourNextLinkBinaryRespon private byte radioChannel = 0; - protected ChannelNegotiateResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + protected ChannelNegotiateResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException, IOException { super(payload); byte[] responseBytes = this.encode(); @@ -22,6 +25,9 @@ public class ChannelNegotiateResponseMessage extends ContourNextLinkBinaryRespon Log.d(TAG, "negotiateChannel: Check response length"); if (responseBytes.length > 46) { radioChannel = responseBytes[76]; + if (responseBytes[76] != pumpSession.getRadioChannel()) { + throw new IOException(String.format(Locale.getDefault(), "Expected to get a message for channel %d. Got %d", pumpSession.getRadioChannel(), responseBytes[76])); + } } else { radioChannel = ((byte) 0); } 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 6fb940764d0aed3cab785917a8ea8a5ab00bda48..6058fc5bc48ea3b8332b55773c7afa3a5115afd0 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 @@ -11,7 +11,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 26/03/2016. */ -public class EndEHSMMessage extends MedtronicRequestMessage { +public class EndEHSMMessage extends MedtronicSendMessageRequestMessage { public EndEHSMMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.END_EHSM_SESSION, pumpSession, buildPayload()); } 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 da88c60272f80d08eccd0797cabe862743c3d43e..d727510f35222f8baae9c1a73f1d9c962a2eddc2 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 @@ -17,18 +17,13 @@ import info.nightscout.android.medtronic.exception.EncryptionException; * Created by lgoedhart on 26/03/2016. */ public class MedtronicRequestMessage extends ContourNextLinkBinaryRequestMessage { - static int ENVELOPE_SIZE = 11; - static int ENCRYPTED_ENVELOPE_SIZE = 3; + static int ENVELOPE_SIZE = 2; 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), @@ -76,43 +71,6 @@ public class MedtronicRequestMessage extends ContourNextLinkBinaryRequestMessage } - /** - * MedtronicSendMessage: - * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ - * | LE long pumpMAC | byte medtronicSequenceNumber | byte unknown | byte Payload size | byte[] Encrypted Payload bytes | - * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ - * <p/> - * MedtronicSendMessage (decrypted payload): - * +-------------------------+----------------------+----------------------+--------------------+ - * | byte sendSequenceNumber | BE short sendMessageType | byte[] Payload bytes | BE short CCITT CRC | - * +-------------------------+----------------------+----------------------+--------------------+ - */ - protected static byte[] buildPayload(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException { - byte payloadLength = (byte) (payload == null ? 0 : payload.length); - - ByteBuffer sendPayloadBuffer = ByteBuffer.allocate(ENCRYPTED_ENVELOPE_SIZE + payloadLength + CRC_SIZE); - sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN); // I know, this is the default - just being explicit - - sendPayloadBuffer.put(sendSequenceNumber(sendMessageType)); - sendPayloadBuffer.putShort(sendMessageType.value); - if (payloadLength != 0) { - sendPayloadBuffer.put(payload); - } - - sendPayloadBuffer.putShort((short) MessageUtils.CRC16CCITT(sendPayloadBuffer.array(), 0xffff, 0x1021, ENCRYPTED_ENVELOPE_SIZE + payloadLength)); - - ByteBuffer payloadBuffer = ByteBuffer.allocate( ENVELOPE_SIZE + sendPayloadBuffer.capacity() ); - payloadBuffer.order(ByteOrder.LITTLE_ENDIAN); - - payloadBuffer.putLong(pumpSession.getPumpMAC()); - payloadBuffer.put((byte) pumpSession.getMedtronicSequenceNumber()); - payloadBuffer.put((byte) 0x10); - payloadBuffer.put((byte) sendPayloadBuffer.capacity()); - payloadBuffer.put(encrypt( pumpSession.getKey(), pumpSession.getIV(), sendPayloadBuffer.array())); - - 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"); diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessageRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessageRequestMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..ba835fc2c4619f6fc103f8ba80cf8f6bd971a397 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessageRequestMessage.java @@ -0,0 +1,86 @@ +package info.nightscout.android.medtronic.message; + +import info.nightscout.android.medtronic.MedtronicCnlSession; +import info.nightscout.android.medtronic.exception.ChecksumException; +import info.nightscout.android.medtronic.exception.EncryptionException; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +/** + * Created by volker on 18.12.2016. + */ + +public class MedtronicSendMessageRequestMessage extends MedtronicRequestMessage { + static int ENVELOPE_SIZE = 11; + static int ENCRYPTED_ENVELOPE_SIZE = 3; + static int CRC_SIZE = 2; + + public enum SendMessageType { + NO_TYPE(0x0), + BEGIN_EHSM_SESSION(0x412), + TIME_REQUEST(0x0403), + READ_PUMP_STATUS_REQUEST(0x0112), + READ_BASAL_PATTERN_REQUEST(0x0112), + END_EHSM_SESSION(0x412); + + private short value; + + SendMessageType(int messageType) { + value = (short) messageType; + } + } + + protected MedtronicSendMessageRequestMessage(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(CommandType.SEND_MESSAGE, CommandAction.PUMP_REQUEST, pumpSession, buildPayload(sendMessageType, pumpSession, payload)); + } + + /** + * MedtronicSendMessage: + * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ + * | LE long pumpMAC | byte medtronicSequenceNumber | byte unknown | byte Payload size | byte[] Encrypted Payload bytes | + * +-----------------+------------------------------+--------------+-------------------+--------------------------------+ + * <p/> + * MedtronicSendMessage (decrypted payload): + * +-------------------------+----------------------+----------------------+--------------------+ + * | byte sendSequenceNumber | BE short sendMessageType | byte[] Payload bytes | BE short CCITT CRC | + * +-------------------------+----------------------+----------------------+--------------------+ + */ + protected static byte[] buildPayload(SendMessageType sendMessageType, MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException { + byte payloadLength = (byte) (payload == null ? 0 : payload.length); + + ByteBuffer sendPayloadBuffer = ByteBuffer.allocate(ENCRYPTED_ENVELOPE_SIZE + payloadLength + CRC_SIZE); + sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN); // I know, this is the default - just being explicit + + sendPayloadBuffer.put(sendSequenceNumber(sendMessageType)); + sendPayloadBuffer.putShort(sendMessageType.value); + if (payloadLength != 0) { + sendPayloadBuffer.put(payload); + } + + sendPayloadBuffer.putShort((short) MessageUtils.CRC16CCITT(sendPayloadBuffer.array(), 0xffff, 0x1021, ENCRYPTED_ENVELOPE_SIZE + payloadLength)); + + ByteBuffer payloadBuffer = ByteBuffer.allocate( ENVELOPE_SIZE + sendPayloadBuffer.capacity() ); + payloadBuffer.order(ByteOrder.LITTLE_ENDIAN); + + payloadBuffer.putLong(pumpSession.getPumpMAC()); + payloadBuffer.put((byte) pumpSession.getMedtronicSequenceNumber()); + payloadBuffer.put((byte) 0x10); + payloadBuffer.put((byte) sendPayloadBuffer.capacity()); + payloadBuffer.put(encrypt( pumpSession.getKey(), pumpSession.getIV(), sendPayloadBuffer.array())); + + return payloadBuffer.array(); + } + + protected static byte sendSequenceNumber(SendMessageType sendMessageType) { + switch (sendMessageType) { + case BEGIN_EHSM_SESSION: + return (byte) 0x80; + case TIME_REQUEST: + return (byte) 0x02; + case READ_PUMP_STATUS_REQUEST: + return (byte) 0x03; + default: + return 0x00; + } + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessageResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessageResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..48820677d9619a21d925c4e795a4ec4b2e195505 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MedtronicSendMessageResponseMessage.java @@ -0,0 +1,15 @@ +package info.nightscout.android.medtronic.message; + +import info.nightscout.android.medtronic.MedtronicCnlSession; +import info.nightscout.android.medtronic.exception.ChecksumException; +import info.nightscout.android.medtronic.exception.EncryptionException; + +/** + * Created by volker on 18.12.2016. + */ + +public class MedtronicSendMessageResponseMessage extends MedtronicResponseMessage { + protected MedtronicSendMessageResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + super(pumpSession, payload); + } +} 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 accdd14c18f771ef2dc36bdcb222c73c15aad1df..5ce32c2ba5a501ab6db4469e92eb9db86c19a4d2 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 @@ -11,7 +11,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 26/03/2016. */ -public class PumpBasalPatternRequestMessage extends MedtronicRequestMessage { +public class PumpBasalPatternRequestMessage extends MedtronicSendMessageRequestMessage { public PumpBasalPatternRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.READ_BASAL_PATTERN_REQUEST, pumpSession, null); } 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 6911f14b1bcf7ffaaf1619a79b2830e65def9c77..310bef3d11474c5faa617b0bc44395e5a56259b5 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 @@ -10,7 +10,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 27/03/2016. */ -public class PumpBasalPatternResponseMessage extends MedtronicResponseMessage { +public class PumpBasalPatternResponseMessage extends MedtronicSendMessageResponseMessage { protected PumpBasalPatternResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { super(pumpSession, payload); 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 87fc2f07edb45178891386b8c395091bd3735db1..043fba57c037d52c7e4d5f61e4a2f3fff50dea7d 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 @@ -11,7 +11,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 26/03/2016. */ -public class PumpStatusRequestMessage extends MedtronicRequestMessage { +public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage { public PumpStatusRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.READ_PUMP_STATUS_REQUEST, pumpSession, null); } 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 8033651d3d392809731755089147be84e3bf2925..69afac095b509013813ecc1a3051679ca10c2c50 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 @@ -15,7 +15,7 @@ import info.nightscout.android.model.medtronicNg.PumpStatusEvent; /** * Created by lgoedhart on 27/03/2016. */ -public class PumpStatusResponseMessage extends MedtronicResponseMessage { +public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessage { private static final String TAG = PumpStatusResponseMessage.class.getSimpleName(); // Data from the Medtronic Pump Status message 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 45d36c680918af7061dd788e680876d73f617360..a1128c947dcf59f5d854f6978955e775ff2527ef 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 @@ -11,7 +11,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 26/03/2016. */ -public class PumpTimeRequestMessage extends MedtronicRequestMessage { +public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage { public PumpTimeRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { super(SendMessageType.TIME_REQUEST, pumpSession, null); } 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 84d7039465a637ee6d07f63585552ab99c8c6afc..c7971f97f057e7f7583c0b8ad4dd481b26e663be 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 @@ -13,7 +13,7 @@ import info.nightscout.android.medtronic.exception.EncryptionException; /** * Created by lgoedhart on 27/03/2016. */ -public class PumpTimeResponseMessage extends MedtronicResponseMessage { +public class PumpTimeResponseMessage extends MedtronicSendMessageResponseMessage { private static final String TAG = PumpTimeResponseMessage.class.getSimpleName(); private Date pumpTime;