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 6bea733aa62958af1e2db2d02ef51f3262bf001d..f8d7221cd559f19a863aa9195b10cbd2cdfbcc35 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java @@ -30,6 +30,8 @@ import info.nightscout.android.medtronic.message.PumpStatusRequestMessage; import info.nightscout.android.medtronic.message.PumpStatusResponseMessage; import info.nightscout.android.medtronic.message.PumpTimeRequestMessage; import info.nightscout.android.medtronic.message.PumpTimeResponseMessage; +import info.nightscout.android.medtronic.message.ReadHistoryInfoRequestMessage; +import info.nightscout.android.medtronic.message.ReadHistoryInfoResponseMessage; import info.nightscout.android.medtronic.message.ReadInfoRequestMessage; import info.nightscout.android.medtronic.message.ReadInfoResponseMessage; import info.nightscout.android.medtronic.message.RequestLinkKeyRequestMessage; @@ -152,6 +154,8 @@ public class MedtronicCnlReader { if (response.getRadioChannel() == mPumpSession.getRadioChannel()) { break; + } else { + mPumpSession.setRadioChannel((byte)0); } } @@ -175,7 +179,7 @@ public class MedtronicCnlReader { return response.getPumpTime(); } - public PumpStatusEvent updatePumpStatus(PumpStatusEvent pumpRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException { + public PumpStatusEvent updatePumpStatus(PumpStatusEvent pumpRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException, UnexpectedMessageException { Log.d(TAG, "Begin updatePumpStatus"); // FIXME - throw if not in EHSM mode (add a state machine) @@ -196,6 +200,16 @@ public class MedtronicCnlReader { Log.d(TAG, "Finished getBasalPatterns"); } + + public void getHistory() throws EncryptionException, IOException, ChecksumException, TimeoutException, UnexpectedMessageException { + Log.d(TAG, "Begin getHistory"); + // FIXME - throw if not in EHSM mode (add a state machine) + + ReadHistoryInfoResponseMessage response = new ReadHistoryInfoRequestMessage(mPumpSession).send(mDevice); + + Log.d(TAG, "Finished getHistory"); + } + public void endEHSMSession() throws EncryptionException, IOException, TimeoutException, ChecksumException { Log.d(TAG, "Begin endEHSMSession"); new EndEHSMMessage(mPumpSession).send(mDevice); 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 f5489004508db2784ea18ba94c04bb17a1526598..7ade34455c1c3b75a6a985505cee70f14ab80abe 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 @@ -44,7 +44,6 @@ public class ContourNextLinkMessage { } public enum CommandType { - NO_TYPE(0x0), OPEN_CONNECTION(0x10), CLOSE_CONNECTION(0x11), SEND_MESSAGE(0x12), @@ -53,7 +52,9 @@ public class ContourNextLinkMessage { SEND_LINK_KEY(0x17), RECEIVE_MESSAGE(0x80), SEND_MESSAGE_RESPONSE(0x81), - REQUEST_LINK_KEY_RESPONSE(0x86); + REQUEST_LINK_KEY_RESPONSE(0x86), + + NO_TYPE(0x0); private byte value; 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 d727510f35222f8baae9c1a73f1d9c962a2eddc2..27a96f29879708785a3806dd518c22b410805bf3 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 @@ -25,12 +25,19 @@ public class MedtronicRequestMessage extends ContourNextLinkBinaryRequestMessage } 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); + END_EHSM_SESSION(0x412), + + READ_HISTORY_INFO_MESSAGE(0x030C), + READ_HISTORY_MESSAGE(0x0304), + READ_TRACE_HISTORY_MESSAGE(0x0302), + + INITIATE_MULTIPACKET_TRANSFER_COMMAND(0xFF00), + + NO_TYPE(0x0); private short value; 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 5ce32c2ba5a501ab6db4469e92eb9db86c19a4d2..e91db4e6040239f8c51fc1b45e2e6319c07cf8f8 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 @@ -20,9 +20,6 @@ public class PumpBasalPatternRequestMessage extends MedtronicSendMessageRequestM sendMessage(mDevice); // Read the 0x81 - readMessage(mDevice); - - // Read the 0x80 PumpBasalPatternResponseMessage response = new PumpBasalPatternResponseMessage(mPumpSession, readMessage(mDevice)); return response; 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 310bef3d11474c5faa617b0bc44395e5a56259b5..e3f96eb6984e98e341f8cbab06f4d8d196d90ffc 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 @@ -1,16 +1,21 @@ package info.nightscout.android.medtronic.message; +import android.util.Log; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; +import info.nightscout.android.utils.HexDump; /** * Created by lgoedhart on 27/03/2016. */ public class PumpBasalPatternResponseMessage extends MedtronicSendMessageResponseMessage { + private static final String TAG = PumpBasalPatternResponseMessage.class.getSimpleName(); + protected PumpBasalPatternResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { super(pumpSession, payload); @@ -24,10 +29,12 @@ public class PumpBasalPatternResponseMessage extends MedtronicSendMessageRespons } */ - // FIXME - this needs to go into PumpBasalPatternResponseMessage - ByteBuffer basalRatesBuffer = ByteBuffer.allocate(96); + ByteBuffer basalRatesBuffer = ByteBuffer.allocate(payload.length); basalRatesBuffer.order(ByteOrder.BIG_ENDIAN); - basalRatesBuffer.put(this.encode(), 0x39, 96); + basalRatesBuffer.put(this.encode()); + + String responseString = HexDump.dumpHexString(basalRatesBuffer.array()); + Log.d(TAG, "PumpStatus: " + responseString); } 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 043fba57c037d52c7e4d5f61e4a2f3fff50dea7d..c920309790aa2775dc46d7dd58f92bda38ae23a9 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 @@ -7,6 +7,7 @@ import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; +import info.nightscout.android.medtronic.exception.UnexpectedMessageException; /** * Created by lgoedhart on 26/03/2016. @@ -16,7 +17,7 @@ public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage super(SendMessageType.READ_PUMP_STATUS_REQUEST, pumpSession, null); } - public PumpStatusResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException { + public PumpStatusResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException { sendMessage(mDevice); // Read the 0x81 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 69afac095b509013813ecc1a3051679ca10c2c50..377a651f6ca99d25254702a974fad53482437a97 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 @@ -6,10 +6,12 @@ import java.math.BigDecimal; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Date; +import java.util.Locale; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; +import info.nightscout.android.medtronic.exception.UnexpectedMessageException; import info.nightscout.android.model.medtronicNg.PumpStatusEvent; /** @@ -45,17 +47,16 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa private long rtc; private long offset; - protected PumpStatusResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException { + protected PumpStatusResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException, UnexpectedMessageException { super(pumpSession, payload); if (this.encode().length < (57 + 96)) { // Invalid message. Don't try and parse it // TODO - deal with this more elegantly Log.e(TAG, "Invalid message received for updatePumpStatus"); - return; + throw new UnexpectedMessageException("Invalid message received for updatePumpStatus"); } - // FIXME - this needs to go into PumpStatusResponseMessage ByteBuffer statusBuffer = ByteBuffer.allocate(96); statusBuffer.order(ByteOrder.BIG_ENDIAN); statusBuffer.put(this.encode(), 0x39, 96); diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..e2daaf066b167ce65c918735075a9a7dfe5dc236 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java @@ -0,0 +1,41 @@ +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; +import info.nightscout.android.medtronic.exception.ChecksumException; +import info.nightscout.android.medtronic.exception.EncryptionException; +import info.nightscout.android.medtronic.exception.UnexpectedMessageException; + +/** + * Created by lgoedhart on 26/03/2016. + */ +public class ReadHistoryInfoRequestMessage extends MedtronicSendMessageRequestMessage { + public ReadHistoryInfoRequestMessage(MedtronicCnlSession pumpSession) throws EncryptionException, ChecksumException { + super(SendMessageType.READ_BASAL_PATTERN_REQUEST, pumpSession, new byte[] { + 2, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }); + } + + public ReadHistoryInfoResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException { + sendMessage(mDevice); + + // Read the 0x81 + ReadHistoryInfoResponseMessage response = new ReadHistoryInfoResponseMessage(mPumpSession, readMessage(mDevice)); + + return response; + } +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoResponseMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..37805026764644405e1288684bc1a6eeb3a55b91 --- /dev/null +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoResponseMessage.java @@ -0,0 +1,43 @@ +package info.nightscout.android.medtronic.message; + +import android.util.Log; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import info.nightscout.android.medtronic.MedtronicCnlSession; +import info.nightscout.android.medtronic.exception.ChecksumException; +import info.nightscout.android.medtronic.exception.EncryptionException; +import info.nightscout.android.medtronic.exception.UnexpectedMessageException; +import info.nightscout.android.utils.HexDump; + +/** + * Created by lgoedhart on 27/03/2016. + */ +public class ReadHistoryInfoResponseMessage extends MedtronicSendMessageResponseMessage { + private static final String TAG = ReadHistoryInfoResponseMessage.class.getSimpleName(); + + protected ReadHistoryInfoResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException, UnexpectedMessageException { + super(pumpSession, payload); + + + if (this.encode().length < 32) { + // Invalid message. + // TODO - deal with this more elegantly + Log.e(TAG, "Invalid message received for ReadHistoryInfo"); + throw new UnexpectedMessageException("Invalid message received for ReadHistoryInfo"); + } else { + + ByteBuffer basalRatesBuffer = ByteBuffer.allocate(payload.length); + basalRatesBuffer.order(ByteOrder.BIG_ENDIAN); + basalRatesBuffer.put(this.encode()); + + String responseString = HexDump.dumpHexString(basalRatesBuffer.array()); + Log.d(TAG, "ReadHistoryInfo: " + responseString); + Log.d(TAG, "ReadHistoryInfo-length: " + basalRatesBuffer.getLong(28)); + } + + + } + +} diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java index f907b9471f8bcf9ac4d8af1c603ccb47c5690c98..68fa08f757e16e2083a868b8426effd57c59e4ce 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java +++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java @@ -21,6 +21,7 @@ import java.util.Date; import java.util.Locale; import java.util.concurrent.TimeoutException; +import info.nightscout.android.BuildConfig; import info.nightscout.android.R; import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MainActivity; @@ -220,6 +221,7 @@ public class MedtronicCnlIntentService extends IntentService { Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel)); cnlReader.beginEHSMSession(); + // read pump status PumpStatusEvent pumpRecord = realm.createObject(PumpStatusEvent.class); String deviceName = String.format("medtronic-640g://%s", cnlReader.getStickSerial()); @@ -238,6 +240,16 @@ public class MedtronicCnlIntentService extends IntentService { cnlReader.updatePumpStatus(pumpRecord); activePump.getPumpHistory().add(pumpRecord); + // start reading other data in debug only + if (BuildConfig.DEBUG) { + // read basal pattern + //cnlReader.getBasalPatterns(); + + // Read history + //cnlReader.getHistory(); + } + + cnlReader.endEHSMSession(); boolean cancelTransaction = true; diff --git a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java index d73f3e6cdbdda5e2ec8d578fcd6391305c2e4235..ba62b7d376816e440ab08ada10ee9f896e497b6a 100644 --- a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java +++ b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java @@ -82,7 +82,10 @@ public class PumpStatusEvent extends RealmObject { } public void setCgmTrend(CGM_TREND cgmTrend) { - this.cgmTrend = cgmTrend.name(); + if (cgmTrend != null) + this.cgmTrend = cgmTrend.name(); + else + this.cgmTrend = CGM_TREND.NOT_SET.name(); } public void setCgmTrend(String cgmTrend) {