diff --git a/app/src/main/java/info/nightscout/android/USB/USBPower.java b/app/src/main/java/info/nightscout/android/USB/USBPower.java
index 92890b8e0f3577c2a6f4966b2f002da4b65a57ff..cf16a178a2ba8d5b6d8b4da4b13d1138f1391d4d 100644
--- a/app/src/main/java/info/nightscout/android/USB/USBPower.java
+++ b/app/src/main/java/info/nightscout/android/USB/USBPower.java
@@ -1,9 +1,9 @@
 package info.nightscout.android.USB;
 
-import java.io.DataOutputStream;
-
 import android.util.Log;
 
+import java.io.DataOutputStream;
+
 public class USBPower {
 
     private static final String TAG = "USBPower";
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 766a8a6145fd6a2bea03d1ef6d7146fdf97b951e..ca2629e4dba044519a7e4fba2bcbe1c2be007b2d 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java
@@ -4,11 +4,7 @@ import android.util.Log;
 
 import org.apache.commons.lang3.ArrayUtils;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.math.BigDecimal;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -18,37 +14,33 @@ import java.util.concurrent.TimeoutException;
 
 import info.nightscout.android.USB.UsbHidDriver;
 import info.nightscout.android.medtronic.message.BeginEHSMMessage;
-import info.nightscout.android.medtronic.message.ChannelNegotiateMessage;
+import info.nightscout.android.medtronic.message.ChannelNegotiateRequestMessage;
+import info.nightscout.android.medtronic.message.ChannelNegotiateResponseMessage;
 import info.nightscout.android.medtronic.message.ChecksumException;
-import info.nightscout.android.medtronic.message.ContourNextLinkBinaryMessage;
+import info.nightscout.android.medtronic.message.CloseConnectionRequestMessage;
 import info.nightscout.android.medtronic.message.ContourNextLinkCommandMessage;
-import info.nightscout.android.medtronic.message.ContourNextLinkMessage;
-import info.nightscout.android.medtronic.message.ContourNextLinkMessageHandler;
+import info.nightscout.android.medtronic.message.DeviceInfoRequestCommandMessage;
 import info.nightscout.android.medtronic.message.DeviceInfoResponseCommandMessage;
 import info.nightscout.android.medtronic.message.EncryptionException;
 import info.nightscout.android.medtronic.message.EndEHSMMessage;
-import info.nightscout.android.medtronic.message.MedtronicMessage;
-import info.nightscout.android.medtronic.message.MessageUtils;
+import info.nightscout.android.medtronic.message.OpenConnectionRequestMessage;
 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;
 import info.nightscout.android.medtronic.message.PumpTimeResponseMessage;
+import info.nightscout.android.medtronic.message.ReadInfoRequestMessage;
 import info.nightscout.android.medtronic.message.ReadInfoResponseMessage;
 import info.nightscout.android.medtronic.message.RequestLinkKeyRequestMessage;
 import info.nightscout.android.medtronic.message.RequestLinkKeyResponseMessage;
-import info.nightscout.android.medtronic.message.DeviceInfoRequestCommandMessage;
 import info.nightscout.android.medtronic.message.UnexpectedMessageException;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
-import info.nightscout.android.utils.HexDump;
 
 /**
  * Created by lgoedhart on 24/03/2016.
  */
-public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
-
+public class MedtronicCnlReader {
     private static final String TAG = MedtronicCnlReader.class.getSimpleName();
 
     private static final int USB_BLOCKSIZE = 64;
@@ -59,34 +51,12 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
     private UsbHidDriver mDevice;
 
     private MedtronicCnlSession mPumpSession = new MedtronicCnlSession();
-
     private String mStickSerial = null;
 
     public MedtronicCnlReader(UsbHidDriver device) {
         mDevice = device;
     }
 
-    private static PumpStatusEvent.CGM_TREND fromMessageByte(byte messageByte) {
-        switch (messageByte) {
-            case (byte) 0x60:
-                return PumpStatusEvent.CGM_TREND.FLAT;
-            case (byte) 0xc0:
-                return PumpStatusEvent.CGM_TREND.DOUBLE_UP;
-            case (byte) 0xa0:
-                return PumpStatusEvent.CGM_TREND.SINGLE_UP;
-            case (byte) 0x80:
-                return PumpStatusEvent.CGM_TREND.FOURTY_FIVE_UP;
-            case (byte) 0x40:
-                return PumpStatusEvent.CGM_TREND.FOURTY_FIVE_DOWN;
-            case (byte) 0x20:
-                return PumpStatusEvent.CGM_TREND.SINGLE_DOWN;
-            case (byte) 0x00:
-                return PumpStatusEvent.CGM_TREND.DOUBLE_DOWN;
-            default:
-                return PumpStatusEvent.CGM_TREND.NOT_COMPUTABLE;
-        }
-    }
-
     public String getStickSerial() {
         return mStickSerial;
     }
@@ -95,75 +65,6 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         return mPumpSession;
     }
 
-    public byte[] readMessage() 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();
-    }
-
-    @Override
-    public void sendMessage(ContourNextLinkMessage message) throws IOException {
-        sendMessage(message.encode());
-        if (message instanceof ContourNextLinkBinaryMessage) {
-            mPumpSession.incrBayerSequenceNumber();
-        }
-
-        if (message instanceof MedtronicMessage) {
-            mPumpSession.incrMedtronicSequenceNumber();
-        }
-    }
-
-    @Override
-    public ContourNextLinkMessage receiveMessage() {
-        return null;
-    }
-
-    public void sendMessage(byte[] message) throws IOException {
-
-        int pos = 0;
-
-        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);
-        }
-    }
-
     public void requestDeviceInfo()
             throws IOException, TimeoutException, UnexpectedMessageException, ChecksumException, EncryptionException {
         DeviceInfoResponseCommandMessage response = new DeviceInfoRequestCommandMessage(mPumpSession).send(mDevice);
@@ -172,7 +73,6 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         mStickSerial = response.getSerial();
     }
 
-
     public void enterControlMode() throws IOException, TimeoutException, UnexpectedMessageException, ChecksumException, EncryptionException {
         boolean doRetry;
 
@@ -185,7 +85,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
                         .send(mDevice).checkControlMessage(ContourNextLinkCommandMessage.ASCII.ACK);
             } catch (UnexpectedMessageException e2) {
                 try {
-                    new ContourNextLinkCommandMessage(ContourNextLinkCommandMessage.ASCII.EOT).send(this);
+                    new ContourNextLinkCommandMessage(ContourNextLinkCommandMessage.ASCII.EOT).send(mDevice);
                 } catch (IOException e) {}
                 finally {
                     doRetry = true;
@@ -205,11 +105,9 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         Log.d(TAG, "Finished enterPasshtroughMode");
     }
 
-    public void openConnection() throws IOException, TimeoutException, NoSuchAlgorithmException, ChecksumException {
+    public void openConnection() throws IOException, TimeoutException, NoSuchAlgorithmException, ChecksumException, EncryptionException {
         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
-        readMessage();
+        new OpenConnectionRequestMessage(mPumpSession, mPumpSession.getHMAC()).send(mDevice);
         Log.d(TAG, "Finished openConnection");
     }
 
@@ -234,7 +132,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         Log.d(TAG, String.format("Finished requestLinkKey. linkKey = '%s'", this.getPumpSession().getKey()));
     }
 
-    public byte negotiateChannel(byte lastRadioChannel) throws IOException, ChecksumException, TimeoutException {
+    public byte negotiateChannel(byte lastRadioChannel) throws IOException, ChecksumException, TimeoutException, EncryptionException {
         ArrayList<Byte> radioChannels = new ArrayList<>(Arrays.asList(ArrayUtils.toObject(RADIO_CHANNELS)));
 
         if (lastRadioChannel != 0x00) {
@@ -250,26 +148,12 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         for (byte channel : radioChannels) {
             Log.d(TAG, String.format("negotiateChannel: trying channel '%d'...", channel));
             mPumpSession.setRadioChannel(channel);
-            new ChannelNegotiateMessage(mPumpSession).send(this);
-
-            // Don't care what the 0x81 response message is at this stage
-            Log.d(TAG, "negotiateChannel: Reading 0x81 message");
-            readMessage();
-            // The 0x80 message
-            Log.d(TAG, "negotiateChannel: Reading 0x80 message");
-            ContourNextLinkMessage response = ContourNextLinkBinaryMessage.fromBytes(readMessage());
-            byte[] responseBytes = response.encode();
-
-            Log.d(TAG, "negotiateChannel: Check response length");
-            if (responseBytes.length > 46) {
-                // Looks promising, let's check the last byte of the payload to make sure
-                if (responseBytes[76] == mPumpSession.getRadioChannel()) {
-                    break;
-                } else {
-                    throw new IOException(String.format(Locale.getDefault(), "Expected to get a message for channel %d. Got %d", mPumpSession.getRadioChannel(), responseBytes[76]));
-                }
+            ChannelNegotiateResponseMessage response = new ChannelNegotiateRequestMessage(mPumpSession).send(mDevice);
+
+            if (response.getRadioChannel() == mPumpSession.getRadioChannel()) {
+                break;
             } else {
-                mPumpSession.setRadioChannel((byte) 0);
+                throw new IOException(String.format(Locale.getDefault(), "Expected to get a message for channel %d. Got %d", mPumpSession.getRadioChannel(), response.getRadioChannel()));
             }
         }
 
@@ -279,9 +163,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
 
     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
-        readMessage();
+        new BeginEHSMMessage(mPumpSession).send(mDevice);
         Log.d(TAG, "Finished beginEHSMSession");
     }
 
@@ -289,172 +171,42 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         Log.d(TAG, "Begin getPumpTime");
         // FIXME - throw if not in EHSM mode (add a state machine)
 
-        new PumpTimeRequestMessage(mPumpSession).send(this);
-        // Read the 0x81
-        readMessage();
-
-        // Read the 0x80
-        ContourNextLinkMessage response = PumpTimeResponseMessage.fromBytes(mPumpSession, readMessage());
-
-        if (response.encode().length < (61 + 8)) {
-            // Invalid message. Return an invalid date.
-            // TODO - deal with this more elegantly
-            Log.e(TAG, "Invalid message received for getPumpTime");
-            return new Date();
-        }
-
-        // FIXME - this needs to go into PumpTimeResponseMessage
-        ByteBuffer dateBuffer = ByteBuffer.allocate(8);
-        dateBuffer.order(ByteOrder.BIG_ENDIAN);
-        dateBuffer.put(response.encode(), 0x3d, 8);
-        long rtc = dateBuffer.getInt(0) & 0x00000000ffffffffL;
-        long offset = dateBuffer.getInt(4);
+        PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice);
 
-        Log.d(TAG, "Finished getPumpTime with date " + MessageUtils.decodeDateTime(rtc, offset));
-        return MessageUtils.decodeDateTime(rtc, offset);
+        Log.d(TAG, "Finished getPumpTime with date " + response.getPumpTime());
+        return response.getPumpTime();
     }
 
-    public void getPumpStatus(PumpStatusEvent pumpRecord, long pumpTimeOffset) throws IOException, EncryptionException, ChecksumException, TimeoutException {
-        Log.d(TAG, "Begin getPumpStatus");
-        // FIXME - throw if not in EHSM mode (add a state machine)
-
-        new PumpStatusRequestMessage(mPumpSession).send(this);
-        // Read the 0x81
-        readMessage();
-
-        // Read the 0x80
-        ContourNextLinkMessage response = PumpStatusResponseMessage.fromBytes(mPumpSession, readMessage());
+    public PumpStatusEvent updatePumpStatus(PumpStatusEvent pumpRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException {
+        Log.d(TAG, "Begin updatePumpStatus");
 
-        if (response.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 getPumpStatus");
-            return;
-        }
-
-        // FIXME - this needs to go into PumpStatusResponseMessage
-        ByteBuffer statusBuffer = ByteBuffer.allocate(96);
-        statusBuffer.order(ByteOrder.BIG_ENDIAN);
-        statusBuffer.put(response.encode(), 0x39, 96);
-
-        // Status Flags
-        pumpRecord.setSuspended((statusBuffer.get(0x03) & 0x01) != 0x00);
-        pumpRecord.setBolusing((statusBuffer.get(0x03) & 0x02) != 0x00);
-        pumpRecord.setDeliveringInsulin((statusBuffer.get(0x03) & 0x10) != 0x00);
-        pumpRecord.setTempBasalActive((statusBuffer.get(0x03) & 0x20) != 0x00);
-        pumpRecord.setCgmActive((statusBuffer.get(0x03) & 0x40) != 0x00);
-
-        // Active basal pattern
-        pumpRecord.setActiveBasalPattern(statusBuffer.get(0x1a));
-
-        // Normal basal rate
-        long rawNormalBasal = statusBuffer.getInt(0x1b);
-        pumpRecord.setBasalRate(new BigDecimal(rawNormalBasal / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
-
-        // Temp basal rate
-        // TODO - need to figure this one out
-        //long rawTempBasal = statusBuffer.getShort(0x21) & 0x0000ffff;
-        //pumpRecord.setTempBasalRate(new BigDecimal(rawTempBasal / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
-
-        // Temp basal percentage
-        pumpRecord.setTempBasalPercentage(statusBuffer.get(0x23));
-
-        // Temp basal minutes remaining
-        pumpRecord.setTempBasalMinutesRemaining((short) (statusBuffer.getShort(0x24) & 0x0000ffff));
-
-        // Units of insulin delivered as basal today
-        // TODO - is this basal? Do we have a total Units delivered elsewhere?
-        pumpRecord.setBasalUnitsDeliveredToday(statusBuffer.getInt(0x26));
-
-        // Pump battery percentage
-        pumpRecord.setBatteryPercentage((statusBuffer.get(0x2a)));
-
-        // Reservoir amount
-        long rawReservoirAmount = statusBuffer.getInt(0x2b);
-        pumpRecord.setReservoirAmount(new BigDecimal(rawReservoirAmount / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
-
-        // Amount of insulin left in pump (in minutes)
-        byte insulinHours = statusBuffer.get(0x2f);
-        byte insulinMinutes = statusBuffer.get(0x30);
-        pumpRecord.setMinutesOfInsulinRemaining((short) ((insulinHours * 60) + insulinMinutes));
-
-        // Active insulin
-        long rawActiveInsulin = statusBuffer.getShort(0x33) & 0x0000ffff;
-        pumpRecord.setActiveInsulin(new BigDecimal(rawActiveInsulin / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
-
-        // CGM SGV
-        pumpRecord.setSgv(statusBuffer.getShort(0x35) & 0x0000ffff); // In mg/DL. 0 means no CGM reading
-
-        // SGV Date
-        long rtc;
-        long offset;
-        if ((pumpRecord.getSgv() & 0x200) == 0x200) {
-            // Sensor error. Let's reset. FIXME - solve this more elegantly later
-            pumpRecord.setSgv(0);
-            rtc = 0;
-            offset = 0;
-            pumpRecord.setCgmTrend(PumpStatusEvent.CGM_TREND.NOT_SET);
-        } else {
-            rtc = statusBuffer.getInt(0x37) & 0x00000000ffffffffL;
-            offset = statusBuffer.getInt(0x3b);
-            pumpRecord.setCgmTrend(fromMessageByte(statusBuffer.get(0x40)));
-        }
-        // TODO - this should go in the sgvDate, and eventDate should be the time of this poll.
-        pumpRecord.setEventDate(new Date(MessageUtils.decodeDateTime(rtc, offset).getTime() - pumpTimeOffset));
-
-        // Predictive low suspend
-        // TODO - there is more status info in this byte other than just a boolean yes/no
-        pumpRecord.setLowSuspendActive(statusBuffer.get(0x3f) != 0);
+        // FIXME - throw if not in EHSM mode (add a state machine)
+        PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice);
+        response.updatePumpRecord(pumpRecord);
 
-        // Recent Bolus Wizard BGL
-        pumpRecord.setRecentBolusWizard(statusBuffer.get(0x48) != 0);
-        pumpRecord.setBolusWizardBGL(statusBuffer.getShort(0x49) & 0x0000ffff); // In mg/DL
+        Log.d(TAG, "Finished updatePumpStatus");
 
-        Log.d(TAG, "Finished getPumpStatus");
+        return pumpRecord;
     }
 
     public void getBasalPatterns() throws EncryptionException, IOException, ChecksumException, TimeoutException {
         Log.d(TAG, "Begin getBasalPatterns");
         // FIXME - throw if not in EHSM mode (add a state machine)
 
-        new PumpBasalPatternRequestMessage(mPumpSession).send(this);
-        // Read the 0x81
-        readMessage();
-
-        // Read the 0x80
-        ContourNextLinkMessage response = PumpBasalPatternResponseMessage.fromBytes(mPumpSession, readMessage());
-
-        // TODO - determine message validity
-        /*
-        if (response.encode().length < (61 + 8)) {
-            // Invalid message.
-            // TODO - deal with this more elegantly
-            Log.e(TAG, "Invalid message received for getBasalPatterns");
-            return;
-        }
-        */
-
-        // FIXME - this needs to go into PumpBasalPatternResponseMessage
-        ByteBuffer basalRatesBuffer = ByteBuffer.allocate(96);
-        basalRatesBuffer.order(ByteOrder.BIG_ENDIAN);
-        basalRatesBuffer.put(response.encode(), 0x39, 96);
+        PumpBasalPatternResponseMessage response = new PumpBasalPatternRequestMessage(mPumpSession).send(mDevice);
 
         Log.d(TAG, "Finished getBasalPatterns");
     }
 
     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
-        readMessage();
+        new EndEHSMMessage(mPumpSession).send(mDevice);
         Log.d(TAG, "Finished endEHSMSession");
     }
 
-    public void closeConnection() throws IOException, TimeoutException, ChecksumException {
+    public void closeConnection() throws IOException, TimeoutException, ChecksumException, EncryptionException, NoSuchAlgorithmException {
         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
-        readMessage();
+        new CloseConnectionRequestMessage(mPumpSession, mPumpSession.getHMAC()).send(mDevice);
         Log.d(TAG, "Finished closeConnection");
     }
 
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 804ce6d2d75b17522bd6ef046229e33397104d65..d43c2c8b3aebc2cc903c7ebee783dc509a74812e 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,6 +1,7 @@
 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;
@@ -18,8 +19,10 @@ public class BeginEHSMMessage extends MedtronicRequestMessage {
         return new byte[] { 0x00 };
     }
 
-    protected void sendMessage(UsbHidDriver mDevice) throws IOException {
-        super.sendMessage(mDevice);
-        mPumpSession.incrMedtronicSequenceNumber();
+    public void send(UsbHidDriver mDevice) throws IOException, TimeoutException {
+        sendMessage(mDevice);
+
+        // The Begin EHSM Session only has an 0x81 response
+        readMessage(mDevice);
     }
 }
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java
similarity index 50%
rename from app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java
rename to app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java
index 544caaf5098ec6b5f46f5303099b2cc92b026297..5121641ef319c7de5437cb3efc7dca238a71becd 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java
@@ -1,18 +1,37 @@
 package info.nightscout.android.medtronic.message;
 
+import android.util.Log;
+
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+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 ChannelNegotiateMessage extends MedtronicRequestMessage {
-    public ChannelNegotiateMessage(MedtronicCnlSession pumpSession) throws ChecksumException {
+public class ChannelNegotiateRequestMessage extends MedtronicRequestMessage {
+    private static final String TAG = ChannelNegotiateRequestMessage.class.getSimpleName();
+
+    public ChannelNegotiateRequestMessage(MedtronicCnlSession pumpSession) throws ChecksumException {
         super(CommandType.SEND_MESSAGE, CommandAction.CHANNEL_NEGOTIATE, pumpSession, buildPayload(pumpSession));
     }
 
+    public ChannelNegotiateResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException {
+
+        // Don't care what the 0x81 response message is at this stage
+        Log.d(TAG, "negotiateChannel: Reading 0x81 message");
+        readMessage(mDevice);
+        // The 0x80 message
+        Log.d(TAG, "negotiateChannel: Reading 0x80 message");
+        ChannelNegotiateResponseMessage response = new ChannelNegotiateResponseMessage(mPumpSession, readMessage(mDevice));
+
+        return response;
+    }
+
     protected static byte[] buildPayload( MedtronicCnlSession pumpSession ) {
         ByteBuffer payload = ByteBuffer.allocate(26);
         payload.order(ByteOrder.LITTLE_ENDIAN);
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
new file mode 100644
index 0000000000000000000000000000000000000000..39a75d6daa6b8821d957eb13b0389a91189a558f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateResponseMessage.java
@@ -0,0 +1,31 @@
+package info.nightscout.android.medtronic.message;
+
+import android.util.Log;
+
+import info.nightscout.android.medtronic.MedtronicCnlSession;
+
+/**
+ * Created by lgoedhart on 27/03/2016.
+ */
+public class ChannelNegotiateResponseMessage extends MedtronicResponseMessage {
+    private static final String TAG = ChannelNegotiateResponseMessage.class.getSimpleName();
+
+    private byte radioChannel = 0;
+
+    protected ChannelNegotiateResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException {
+        super(pumpSession, payload);
+
+        byte[] responseBytes = this.encode();
+
+        Log.d(TAG, "negotiateChannel: Check response length");
+        if (responseBytes.length > 46) {
+            radioChannel = responseBytes[76];
+        } else {
+            radioChannel = ((byte) 0);
+        }
+    }
+
+    public byte getRadioChannel() {
+        return radioChannel;
+    }
+}
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java
index 24238af71c62fcb961b147a8c1dd4fe7ac2789ee..b560cfe56f4691ea64827602865dcb5d6f3fe3ce 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java
@@ -4,7 +4,6 @@ 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;
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
index 549ee889560c0c04b62bf54824b202501f70f672..89adf9980d64a024c87144334b4d2d47032c7f2c 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryResponseMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryResponseMessage.java
@@ -1,9 +1,5 @@
 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.
  */
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 9839f752f66b52f66837536f6928a1248d5077e2..b5edb78c6158b8c0a3414f25d65e5c9f77dfe864 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,7 +4,6 @@ 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.
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
index 12f9b9575057a497020176d2f00254cc9a934faf..4cbf4153ca38c8a20cf2254c81c51bd74d018ab0 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponse.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponse.java
@@ -1,7 +1,5 @@
 package info.nightscout.android.medtronic.message;
 
-import info.nightscout.android.medtronic.MedtronicCnlSession;
-
 /**
  * Created by volker on 10.12.2016.
  */
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 36d39a48205ed0a53d047efc1b91879539320121..1c8d92aea954fc08f072d89d3f2111e7310a2f4e 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,15 +5,11 @@ 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;
-import info.nightscout.android.medtronic.MedtronicCnlSession;
 import info.nightscout.android.utils.HexDump;
 
-import static android.R.id.message;
-
 /**
  * Created by lgoedhart on 26/03/2016.
  */
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessageHandler.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessageHandler.java
deleted file mode 100644
index 1d669f67b84cd9118e11c91966db05ff95f8738c..0000000000000000000000000000000000000000
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessageHandler.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package info.nightscout.android.medtronic.message;
-
-import java.io.IOException;
-
-/**
- * Created by lgoedhart on 26/03/2016.
- */
-public interface ContourNextLinkMessageHandler {
-    void sendMessage( ContourNextLinkMessage message ) throws IOException;
-    ContourNextLinkMessage receiveMessage();
-}
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
index 390380d6b4d5bb88a4683a2c98e35d049ef71b95..036c185f290caa5a8e0fbbe7ca37a51b83d92f5e 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java
@@ -1,14 +1,6 @@
 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.
  */
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 24d6aa8b59000418060a7d4f44e30b2637716d92..3dd5141f561ba34948cb46956ec6555fd1f916f4 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
@@ -1,17 +1,9 @@
 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;
-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.
  */
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 1400a2699299fd903315fbff494cbbf41f0d8aca..fec7c00038cfa9368ee6340ecff94ce5e5bf7311 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,10 +6,6 @@ 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/EndEHSMMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java
index fc7c4dd6f46e9a8a5788e79c7628027ccde16951..9db6c036bc3dd253b191715caa595a02570f645c 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,6 +1,7 @@
 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;
@@ -18,8 +19,10 @@ public class EndEHSMMessage extends MedtronicRequestMessage {
         return new byte[] { 0x01 };
     }
 
-    protected void sendMessage(UsbHidDriver mDevice) throws IOException {
-        super.sendMessage(mDevice);
-        mPumpSession.incrMedtronicSequenceNumber();
+    public void send(UsbHidDriver mDevice) throws IOException, TimeoutException {
+        sendMessage(mDevice);
+
+        // The End EHSM Session only has an 0x81 response
+        readMessage(mDevice);
     }
 }
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 8557561507042e5a23c857a9c5bca483334d7472..dcc926cc16b7166eb54f4a3b0ab30538d9591675 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
@@ -1,13 +1,13 @@
 package info.nightscout.android.medtronic.message;
 
-import info.nightscout.android.medtronic.MedtronicCnlSession;
-
 import java.nio.ByteBuffer;
 
 import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
+import info.nightscout.android.medtronic.MedtronicCnlSession;
+
 /**
  * Created by lgoedhart on 26/03/2016.
  */
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
index 38f4ffb75dd967fff04f05782ea22d428540510f..b061ebd1f08683f49d0f834338fbef0179856171 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java
@@ -1,8 +1,5 @@
 package info.nightscout.android.medtronic.message;
 
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
 import info.nightscout.android.medtronic.MedtronicCnlSession;
 
 /**
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 a00715319d580be7e5ab90d8cb00af3ccc2ba802..d341f775bc8fcb75ff944611dcc3440ed53e402a 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,6 +1,7 @@
 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;
@@ -13,8 +14,13 @@ public class PumpBasalPatternRequestMessage extends MedtronicRequestMessage {
         super(SendMessageType.READ_BASAL_PATTERN_REQUEST, pumpSession, null);
     }
 
-    protected void sendMessage(UsbHidDriver mDevice) throws IOException {
-        super.sendMessage(mDevice);
-        mPumpSession.incrMedtronicSequenceNumber();
+    public PumpBasalPatternResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException {
+        // 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 43132b661edfbcb0e2e3f2d66c5b39147cdb5646..daef88a0d8824f35dc9dec5dc391b1906ecb040c 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,5 +1,8 @@
 package info.nightscout.android.medtronic.message;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
 import info.nightscout.android.medtronic.MedtronicCnlSession;
 
 /**
@@ -8,14 +11,22 @@ import info.nightscout.android.medtronic.MedtronicCnlSession;
 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 = MedtronicResponseMessage.fromBytes(pumpSession, bytes);
+        // TODO - determine message validity
+        /*
+        if (response.encode().length < (61 + 8)) {
+            // Invalid message.
+            // TODO - deal with this more elegantly
+            Log.e(TAG, "Invalid message received for getBasalPatterns");
+            return;
+        }
+        */
 
-        // TODO - Validate the MessageType
+        // FIXME - this needs to go into PumpBasalPatternResponseMessage
+        ByteBuffer basalRatesBuffer = ByteBuffer.allocate(96);
+        basalRatesBuffer.order(ByteOrder.BIG_ENDIAN);
+        basalRatesBuffer.put(this.encode(), 0x39, 96);
 
-        return message;
     }
+
 }
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 0c507a6ae06e91133a3188896ed8e41aa46be7fd..9532cb631c1584cb63df043a54737ae6bc0ce429 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,6 +1,7 @@
 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;
@@ -13,8 +14,14 @@ public class PumpStatusRequestMessage extends MedtronicRequestMessage {
         super(SendMessageType.READ_PUMP_STATUS_REQUEST, pumpSession, null);
     }
 
-    protected void sendMessage(UsbHidDriver mDevice) throws IOException {
-        super.sendMessage(mDevice);
-        mPumpSession.incrMedtronicSequenceNumber();
+    public PumpStatusResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException {
+        sendMessage(mDevice);
+
+        // Read the 0x81
+        readMessage(mDevice);
+
+        PumpStatusResponseMessage response = new PumpStatusResponseMessage(mPumpSession, readMessage(mDevice));
+
+        return response;
     }
 }
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 151348e08ba528e1a0fcbe751db5bbcf81d8e39e..b791a296a21f9beb6fb6e24e0c3caeaae904423d 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
@@ -1,21 +1,191 @@
 package info.nightscout.android.medtronic.message;
 
+import android.util.Log;
+
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Date;
+
 import info.nightscout.android.medtronic.MedtronicCnlSession;
+import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
 
 /**
  * Created by lgoedhart on 27/03/2016.
  */
 public class PumpStatusResponseMessage extends MedtronicResponseMessage {
+    private static final String TAG = PumpStatusResponseMessage.class.getSimpleName();
+
+    // Data from the Medtronic Pump Status message
+    private boolean suspended;
+    private boolean bolusing;
+    private boolean deliveringInsulin;
+    private boolean tempBasalActive;
+    private boolean cgmActive;
+    private byte activeBasalPattern;
+    private float basalRate;
+    private float tempBasalRate;
+    private byte tempBasalPercentage;
+    private short tempBasalMinutesRemaining;
+    private float basalUnitsDeliveredToday;
+    private short batteryPercentage;
+    private float reservoirAmount;
+    private short minutesOfInsulinRemaining; // 25h == "more than 1 day"
+    private float activeInsulin;
+    private int sgv;
+    private Date sgvDate;
+    private boolean lowSuspendActive;
+    private PumpStatusEvent.CGM_TREND cgmTrend;
+
+    private boolean recentBolusWizard; // Whether a bolus wizard has been run recently
+    private int bolusWizardBGL; // in mg/dL. 0 means no recent bolus wizard reading.
+
+    private long rtc;
+    private long offset;
+
     protected PumpStatusResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException {
         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;
+        }
+
+        // FIXME - this needs to go into PumpStatusResponseMessage
+        ByteBuffer statusBuffer = ByteBuffer.allocate(96);
+        statusBuffer.order(ByteOrder.BIG_ENDIAN);
+        statusBuffer.put(this.encode(), 0x39, 96);
+
+        // Status Flags
+        suspended = ((statusBuffer.get(0x03) & 0x01) != 0x00);
+        bolusing = ((statusBuffer.get(0x03) & 0x02) != 0x00);
+        deliveringInsulin = ((statusBuffer.get(0x03) & 0x10) != 0x00);
+        tempBasalActive = ((statusBuffer.get(0x03) & 0x20) != 0x00);
+        cgmActive = ((statusBuffer.get(0x03) & 0x40) != 0x00);
+
+        // Active basal pattern
+        activeBasalPattern = (statusBuffer.get(0x1a));
+
+        // Normal basal rate
+        long rawNormalBasal = statusBuffer.getInt(0x1b);
+        basalRate = (new BigDecimal(rawNormalBasal / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
+
+        // Temp basal rate
+        // TODO - need to figure this one out
+        //long rawTempBasal = statusBuffer.getShort(0x21) & 0x0000ffff;
+        //pumpRecord.setTempBasalRate(new BigDecimal(rawTempBasal / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
+
+        // Temp basal percentage
+        tempBasalPercentage = (statusBuffer.get(0x23));
+
+        // Temp basal minutes remaining
+        tempBasalMinutesRemaining = ((short) (statusBuffer.getShort(0x24) & 0x0000ffff));
+
+        // Units of insulin delivered as basal today
+        // TODO - is this basal? Do we have a total Units delivered elsewhere?
+        basalUnitsDeliveredToday = (statusBuffer.getInt(0x26));
+
+        // Pump battery percentage
+        batteryPercentage = ((statusBuffer.get(0x2a)));
+
+        // Reservoir amount
+        long rawReservoirAmount = statusBuffer.getInt(0x2b);
+        reservoirAmount = (new BigDecimal(rawReservoirAmount / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue());
+
+        // Amount of insulin left in pump (in minutes)
+        byte insulinHours = statusBuffer.get(0x2f);
+        byte insulinMinutes = statusBuffer.get(0x30);
+        minutesOfInsulinRemaining = ((short) ((insulinHours * 60) + insulinMinutes));
+
+        // Active insulin
+        long rawActiveInsulin = statusBuffer.getShort(0x33) & 0x0000ffff;
+        activeInsulin = new BigDecimal(rawActiveInsulin / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP).floatValue();
+        ;
+
+        // CGM SGV
+        sgv = (statusBuffer.getShort(0x35) & 0x0000ffff); // In mg/DL. 0 means no CGM reading
+
+        // SGV Date
+
+        if ((sgv & 0x200) == 0x200) {
+            // Sensor error. Let's reset. FIXME - solve this more elegantly later
+            sgv = 0;
+            rtc = 0;
+            offset = 0;
+            cgmTrend = (PumpStatusEvent.CGM_TREND.NOT_SET);
+        } else {
+            rtc = statusBuffer.getInt(0x37) & 0x00000000ffffffffL;
+            offset = statusBuffer.getInt(0x3b);
+            cgmTrend = (PumpStatusEvent.CGM_TREND.fromMessageByte(statusBuffer.get(0x40)));
+        }
+
+        // TODO - this should go in the sgvDate, and eventDate should be the time of this poll.
+        sgvDate = MessageUtils.decodeDateTime(rtc, offset);
+
+        // Predictive low suspend
+        // TODO - there is more status info in this byte other than just a boolean yes/no
+        lowSuspendActive = (statusBuffer.get(0x3f) != 0);
+
+        // Recent Bolus Wizard BGL
+        recentBolusWizard = (statusBuffer.get(0x48) != 0);
+        bolusWizardBGL = (statusBuffer.getShort(0x49) & 0x0000ffff); // In mg/DL
     }
 
-    public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException {
-        // TODO - turn this into a factory
-        ContourNextLinkMessage message = MedtronicResponseMessage.fromBytes(pumpSession, bytes);
+    /**
+     * update pumpRecord with data read from pump
+     *
+     * @param pumpRecord
+     */
+    public void updatePumpRecord(PumpStatusEvent pumpRecord) {
+        // Status Flags
+        pumpRecord.setSuspended(suspended);
+        pumpRecord.setBolusing(bolusing);
+        pumpRecord.setDeliveringInsulin(deliveringInsulin);
+        pumpRecord.setTempBasalActive(tempBasalActive);
+        pumpRecord.setCgmActive(cgmActive);
+
+        // Active basal pattern
+        pumpRecord.setActiveBasalPattern(activeBasalPattern);
+
+        // Normal basal rate
+        pumpRecord.setBasalRate(basalRate);
+
+        // Temp basal percentage
+        pumpRecord.setTempBasalPercentage(tempBasalPercentage);
+
+        // Temp basal minutes remaining
+        pumpRecord.setTempBasalMinutesRemaining(tempBasalMinutesRemaining);
+
+        // Units of insulin delivered as basal today
+        pumpRecord.setBasalUnitsDeliveredToday(basalUnitsDeliveredToday);
+
+        // Pump battery percentage
+        pumpRecord.setBatteryPercentage(batteryPercentage);
+
+        // Reservoir amount
+        pumpRecord.setReservoirAmount(reservoirAmount);
+
+        // Amount of insulin left in pump (in minutes)
+        pumpRecord.setMinutesOfInsulinRemaining(minutesOfInsulinRemaining);
+
+        // Active insulin
+        pumpRecord.setActiveInsulin(activeInsulin);
+
+        // CGM SGV
+        pumpRecord.setSgv(sgv);
+
+        // SGV Date
+        pumpRecord.setCgmTrend(cgmTrend);
+        pumpRecord.setEventDate(new Date(sgvDate.getTime() - pumpRecord.getPumpTimeOffset()));
 
-        // TODO - Validate the MessageType
+        // Predictive low suspend
+        // TODO - there is more status info in this byte other than just a boolean yes/no
+        pumpRecord.setLowSuspendActive(lowSuspendActive);
 
-        return message;
+        // Recent Bolus Wizard BGL
+        pumpRecord.setRecentBolusWizard(recentBolusWizard);
+        pumpRecord.setBolusWizardBGL(bolusWizardBGL); // In mg/DL
     }
 }
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 c773fa1034cacad0cd1fc3ff355f5969a0e88aae..00343c2cf6930dc70d8cc86d421dc9f87ce83707 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,6 +1,7 @@
 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;
@@ -13,8 +14,13 @@ public class PumpTimeRequestMessage extends MedtronicRequestMessage {
         super(SendMessageType.TIME_REQUEST, pumpSession, null);
     }
 
-    protected void sendMessage(UsbHidDriver mDevice) throws IOException {
-        super.sendMessage(mDevice);
-        mPumpSession.incrMedtronicSequenceNumber();
+    public PumpTimeResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, ChecksumException, EncryptionException {
+        // Read the 0x81
+        readMessage(mDevice);
+
+        // Read the 0x80
+        PumpTimeResponseMessage response = new PumpTimeResponseMessage(mPumpSession, readMessage(mDevice));
+
+        return response;
     }
 }
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 6f1ca90a46d23986267e29670a2d805bc7dd981e..38673913051f2cad684389630d402d2eb919a506 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
@@ -1,21 +1,41 @@
 package info.nightscout.android.medtronic.message;
 
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Date;
+
 import info.nightscout.android.medtronic.MedtronicCnlSession;
 
 /**
  * Created by lgoedhart on 27/03/2016.
  */
 public class PumpTimeResponseMessage extends MedtronicResponseMessage {
+    private static final String TAG = PumpTimeResponseMessage.class.getSimpleName();
+
+    private Date pumpTime;
+
     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 = MedtronicResponseMessage.fromBytes(pumpSession, bytes);
+        if (this.encode().length < (61 + 8)) {
+            // Invalid message. Return an invalid date.
+            // TODO - deal with this more elegantly
+            Log.e(TAG, "Invalid message received for getPumpTime");
+            pumpTime = new Date();
+        }
 
-        // TODO - Validate the MessageType
+        // FIXME - this needs to go into PumpTimeResponseMessage
+        ByteBuffer dateBuffer = ByteBuffer.allocate(8);
+        dateBuffer.order(ByteOrder.BIG_ENDIAN);
+        dateBuffer.put(this.encode(), 0x3d, 8);
+        long rtc = dateBuffer.getInt(0) & 0x00000000ffffffffL;
+        long offset = dateBuffer.getInt(4);
+        pumpTime = MessageUtils.decodeDateTime(rtc, offset);
+    }
 
-        return message;
+    public Date getPumpTime() {
+        return pumpTime;
     }
 }
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 dc2a97bc5538016a753e646acce0499fb04f36db..a15ffa5f319d7c8f0f42804c40a69d77c9462bf2 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
@@ -1,12 +1,11 @@
 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 java.util.concurrent.TimeoutException;
-
 /**
  * Created by volker on 10.12.2016.
  */
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 814f29de870282cf6b54da5c6619dbbadc4f6864..2451ecb361b532fcc4a4d18e94a81e8dbd0d59e7 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
@@ -235,7 +235,7 @@ public class MedtronicCnlIntentService extends IntentService {
                     // TODO - send ACTION to MainActivity to show offset between pump and uploader.
                     pumpRecord.setPumpTimeOffset(pumpOffset);
                     pumpRecord.setPumpDate(new Date(pumpTime - pumpOffset));
-                    cnlReader.getPumpStatus(pumpRecord, pumpOffset);
+                    cnlReader.updatePumpStatus(pumpRecord);
                     activePump.getPumpHistory().add(pumpRecord);
 
                     cnlReader.endEHSMSession();
@@ -270,10 +270,12 @@ public class MedtronicCnlIntentService extends IntentService {
                 Log.e(TAG, "Could not determine CNL HMAC", e);
                 sendStatus("Error connecting to Contour Next Link: Hashing error.");
             } finally {
-                //TODO : 05.11.2016 has the close to be here?
-                cnlReader.closeConnection();
-                cnlReader.endPassthroughMode();
-                cnlReader.endControlMode();
+                try {
+                    cnlReader.closeConnection();
+                    cnlReader.endPassthroughMode();
+                    cnlReader.endControlMode();
+                } catch (NoSuchAlgorithmException e) {}
+
             }
         } catch (IOException e) {
             Log.e(TAG, "Error connecting to Contour Next Link.", e);
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 ab95d50f6d346d506d3a6f03a992e53cfaa00804..d73f3e6cdbdda5e2ec8d578fcd6391305c2e4235 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
@@ -272,6 +272,27 @@ public class PumpStatusEvent extends RealmObject {
         DOUBLE_DOWN,
         NOT_COMPUTABLE,
         RATE_OUT_OF_RANGE,
-        NOT_SET
+        NOT_SET;
+
+        public static CGM_TREND fromMessageByte(byte messageByte) {
+            switch (messageByte) {
+                case (byte) 0x60:
+                    return PumpStatusEvent.CGM_TREND.FLAT;
+                case (byte) 0xc0:
+                    return PumpStatusEvent.CGM_TREND.DOUBLE_UP;
+                case (byte) 0xa0:
+                    return PumpStatusEvent.CGM_TREND.SINGLE_UP;
+                case (byte) 0x80:
+                    return PumpStatusEvent.CGM_TREND.FOURTY_FIVE_UP;
+                case (byte) 0x40:
+                    return PumpStatusEvent.CGM_TREND.FOURTY_FIVE_DOWN;
+                case (byte) 0x20:
+                    return PumpStatusEvent.CGM_TREND.SINGLE_DOWN;
+                case (byte) 0x00:
+                    return PumpStatusEvent.CGM_TREND.DOUBLE_DOWN;
+                default:
+                    return PumpStatusEvent.CGM_TREND.NOT_COMPUTABLE;
+            }
+        }
     }
 }
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
index b542315ff5d471d0dee874e0a08da76ebffe2f75..bcacc3428e19d027a840c7260aa1c3ac8a007912 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
@@ -10,8 +10,6 @@ import android.preference.PreferenceManager;
 import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 
-import org.apache.http.HttpResponse;
-import org.apache.http.StatusLine;
 import org.apache.http.client.ResponseHandler;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;