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 b66a3c12f160c93cfd63f194a529e175366abddb..7e1e44b3f82e3c189ae5cf8cd1c71f6716419cc0 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java
@@ -15,8 +15,6 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.Locale;
 import java.util.concurrent.TimeoutException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import info.nightscout.android.USB.UsbHidDriver;
 import info.nightscout.android.medtronic.message.BeginEHSMMessage;
@@ -26,6 +24,7 @@ import info.nightscout.android.medtronic.message.ContourNextLinkBinaryMessage;
 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.DeviceInfoResponseCommandMessage;
 import info.nightscout.android.medtronic.message.EncryptionException;
 import info.nightscout.android.medtronic.message.EndEHSMMessage;
 import info.nightscout.android.medtronic.message.MedtronicMessage;
@@ -40,6 +39,7 @@ import info.nightscout.android.medtronic.message.PumpTimeResponseMessage;
 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;
@@ -172,73 +172,44 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
         }
     }
 
-    public void requestDeviceInfo() throws IOException, TimeoutException, UnexpectedMessageException {
-        new ContourNextLinkCommandMessage("X").send(this);
+    public void requestDeviceInfo()
+            throws IOException, TimeoutException, UnexpectedMessageException, ChecksumException, EncryptionException {
+        DeviceInfoResponseCommandMessage response = new DeviceInfoRequestCommandMessage().send(mDevice);
 
-        boolean doRetry = false;
-
-        // TODO - parse this into an ASTM record for the device info.
-        try {
-            // The stick will return either the ASTM message, or the ENQ first. The order can change,
-            // so we need to handle both cases
-            byte[] response1 = readMessage();
-            byte[] response2 = readMessage();
-
-            if (response1[0] == ASCII.EOT.value) {
-                // response 1 is the ASTM message
-                checkControlMessage(response2, ASCII.ENQ.value);
-                extractStickSerial(new String(response1));
-            } else {
-                // response 2 is the ASTM message
-                checkControlMessage(response1, ASCII.ENQ.value);
-                extractStickSerial(new String(response2));
-            }
-        } catch (TimeoutException e) {
-            // Terminate comms with the pump, then try again
-            new ContourNextLinkCommandMessage(ASCII.EOT.value).send(this);
-            doRetry = true;
-        } finally {
-            if (doRetry) {
-                requestDeviceInfo();
-            }
-        }
+        //TODO - extract more details form the device info.
+        mStickSerial = response.getSerial();
     }
 
-    private void extractStickSerial(String astmMessage) {
-        Pattern pattern = Pattern.compile(".*?\\^(\\d{4}-\\d{7})\\^.*");
-        Matcher matcher = pattern.matcher(astmMessage);
-        if (matcher.find()) {
-            mStickSerial = matcher.group(1);
-        }
-    }
 
-    public void enterControlMode() throws IOException, TimeoutException, UnexpectedMessageException {
-        boolean doRetry = false;
-
-        try {
-            new ContourNextLinkCommandMessage(ASCII.NAK.value).send(this);
-            checkControlMessage(readMessage(), ASCII.EOT.value);
-            new ContourNextLinkCommandMessage(ASCII.ENQ.value).send(this);
-            checkControlMessage(readMessage(), ASCII.ACK.value);
-        } catch (UnexpectedMessageException e2) {
-            // Terminate comms with the pump, then try again
-            new ContourNextLinkCommandMessage(ASCII.EOT.value).send(this);
-            doRetry = true;
-        } finally {
-            if (doRetry) {
-                enterControlMode();
+    public void enterControlMode() throws IOException, TimeoutException, UnexpectedMessageException, ChecksumException, EncryptionException {
+        boolean doRetry;
+
+        do {
+            doRetry = false;
+            try {
+                new ContourNextLinkCommandMessage(ASCII.NAK.value)
+                        .send(mDevice).checkControlMessage(ASCII.EOT.value);
+                new ContourNextLinkCommandMessage(ASCII.ENQ.value)
+                        .send(mDevice).checkControlMessage(ASCII.ACK.value);
+            } catch (UnexpectedMessageException e2) {
+                try {
+                    new ContourNextLinkCommandMessage(ASCII.EOT.value).send(this);
+                } catch (IOException e) {}
+                finally {
+                    doRetry = true;
+                }
             }
-        }
+        } while (doRetry);
     }
 
-    public void enterPassthroughMode() throws IOException, TimeoutException, UnexpectedMessageException {
+    public void enterPassthroughMode() throws IOException, TimeoutException, UnexpectedMessageException, ChecksumException, EncryptionException {
         Log.d(TAG, "Begin enterPasshtroughMode");
-        new ContourNextLinkCommandMessage("W|").send(this);
-        checkControlMessage(readMessage(), ASCII.ACK.value);
-        new ContourNextLinkCommandMessage("Q|").send(this);
-        checkControlMessage(readMessage(), ASCII.ACK.value);
-        new ContourNextLinkCommandMessage("1|").send(this);
-        checkControlMessage(readMessage(), ASCII.ACK.value);
+        new ContourNextLinkCommandMessage("W|")
+                .send(mDevice).checkControlMessage(ASCII.ACK.value);
+        new ContourNextLinkCommandMessage("Q|")
+                .send(mDevice).checkControlMessage(ASCII.ACK.value);
+        new ContourNextLinkCommandMessage("1|")
+                .send(mDevice).checkControlMessage(ASCII.ACK.value);
         Log.d(TAG, "Finished enterPasshtroughMode");
     }
 
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java
index 4a3f94bd07cacac066df13a416f51f06b4e6e3d3..c93aa7fb6d2f02c96c8e504dec348f449a6920f4 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryMessage.java
@@ -7,6 +7,7 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Locale;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Created by lgoedhart on 26/03/2016.
@@ -14,7 +15,6 @@ import java.util.Locale;
 public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage {
     //protected ByteBuffer mBayerEnvelope;
     //protected ByteBuffer mBayerPayload;
-    protected MedtronicCnlSession mPumpSession;
     protected CommandType mCommandType = CommandType.NO_TYPE;
 
     static int ENVELOPE_SIZE = 33;
@@ -56,6 +56,19 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage {
         }
     }
 
+    public static ContourNextLinkMessage fromBytes(byte[] bytes) throws ChecksumException {
+        ContourNextLinkMessage message = new ContourNextLinkMessage(bytes);
+        message.validate();
+
+        return message;
+    }
+
+
+    public void checkControlMessage(byte controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException {
+        checkControlMessage(mPayload.array(), controlCharacter);
+    }
+
+
     /**
      * Handle incrementing sequence number
      *
@@ -96,13 +109,6 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage {
         return payloadBuffer.array();
     }
 
-    public static ContourNextLinkMessage fromBytes(byte[] bytes) throws ChecksumException {
-        ContourNextLinkMessage message = new ContourNextLinkMessage(bytes);
-        message.validate();
-
-        return message;
-    }
-
     protected void validate(ContourNextLinkMessage message)  throws ChecksumException {
         // Validate checksum
         byte messageChecksum = message.mPayload.get(32);
@@ -111,7 +117,13 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage {
         if (messageChecksum != calculatedChecksum) {
             throw new ChecksumException(String.format(Locale.getDefault(), "Expected to get %d. Got %d", (int) calculatedChecksum, (int) messageChecksum));
         }
+    }
 
-
+    protected void checkControlMessage(byte[] msg, byte controlCharacter) throws IOException, TimeoutException, UnexpectedMessageException {
+        if (msg.length != 1 || msg[0] != controlCharacter) {
+            throw new UnexpectedMessageException(String.format(Locale.getDefault(), "Expected to get control character '%d' Got '%d'.",
+                    (int) controlCharacter, (int) msg[0]));
+        }
     }
+
 }
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 ad114c682a2eeac28d4e1e19a0f42a1131a72c26..c7dc1ab6535d3390577c91c8ee60744cc2348c80 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
@@ -1,5 +1,10 @@
 package info.nightscout.android.medtronic.message;
 
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import info.nightscout.android.USB.UsbHidDriver;
+
 /**
  * Created by lgoedhart on 26/03/2016.
  */
@@ -11,4 +16,12 @@ public class ContourNextLinkCommandMessage extends ContourNextLinkMessage {
     public ContourNextLinkCommandMessage(String command) {
         super(command.getBytes());
     }
+
+    public ContourNextLinkCommandResponseMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException, UnexpectedMessageException {
+        sendMessage(mDevice);
+
+        ContourNextLinkCommandResponseMessage response = new ContourNextLinkCommandResponseMessage(mPumpSession, readMessage(mDevice));;
+
+        return response;
+    }
 }
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponseMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5bde36799dda28dfcc2ffbd84d9324e168d806a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandResponseMessage.java
@@ -0,0 +1,13 @@
+package info.nightscout.android.medtronic.message;
+
+import info.nightscout.android.medtronic.MedtronicCnlSession;
+
+/**
+ * Created by volker on 10.12.2016.
+ */
+public class ContourNextLinkCommandResponseMessage extends ContourNextLinkBinaryMessage {
+
+    public ContourNextLinkCommandResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws ChecksumException {
+        super(CommandType.NO_TYPE, pumpSession, payload);
+    }
+}
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java
index 2639e76c56591663bd69c1745892e11de2603ec9..159ac178835177155bf6f69bbeb475130b75bcbd 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
@@ -8,6 +8,7 @@ import java.nio.ByteBuffer;
 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;
@@ -23,6 +24,7 @@ public class ContourNextLinkMessage {
     private static final String BAYER_USB_HEADER = "ABC";
 
     protected ByteBuffer mPayload;
+    protected MedtronicCnlSession mPumpSession;
 
     protected ContourNextLinkMessage(byte[] bytes) {
         setPayload(bytes);
@@ -99,4 +101,19 @@ public class ContourNextLinkMessage {
     }
 
     protected void validate() {};
+
+
+    public enum ASCII {
+        STX(0x02),
+        EOT(0x04),
+        ENQ(0x05),
+        ACK(0x06),
+        NAK(0x15);
+
+        protected byte value;
+
+        ASCII(int code) {
+            this.value = (byte) code;
+        }
+    }
 }
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..0aab014e551a3b773d51797caf315f2de68a884e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoRequestCommandMessage.java
@@ -0,0 +1,44 @@
+package info.nightscout.android.medtronic.message;
+
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import info.nightscout.android.USB.UsbHidDriver;
+
+/**
+ * Created by volker on 10.12.2016.
+ */
+
+public class DeviceInfoRequestCommandMessage extends ContourNextLinkMessage {
+    public DeviceInfoRequestCommandMessage() {
+        super("X".getBytes());
+    }
+
+    public DeviceInfoResponseCommandMessage send(UsbHidDriver mDevice) throws IOException, TimeoutException, EncryptionException, ChecksumException, UnexpectedMessageException {
+        sendMessage(mDevice);
+
+        byte[] response1 = readMessage(mDevice);
+        byte[] response2 = readMessage(mDevice);
+
+        boolean doRetry = false;
+        DeviceInfoResponseCommandMessage response = null;
+
+        do {
+            try {
+                if (response1[0] == ASCII.EOT.value) {
+                    // response 1 is the ASTM message
+                    response = new DeviceInfoResponseCommandMessage(mPumpSession, response1);
+                    response.checkControlMessage(response2, ASCII.ENQ.value);
+                } else {
+                    // response 2 is the ASTM message
+                    response = new DeviceInfoResponseCommandMessage(mPumpSession, response1);
+                    response.checkControlMessage(response1, ASCII.ENQ.value);
+                }
+            } catch (TimeoutException e) {
+                doRetry = true;
+            }
+        } while (doRetry);
+
+        return response;
+    }
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..fec7c00038cfa9368ee6340ecff94ce5e5bf7311
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/DeviceInfoResponseCommandMessage.java
@@ -0,0 +1,35 @@
+package info.nightscout.android.medtronic.message;
+
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import info.nightscout.android.medtronic.MedtronicCnlSession;
+
+/**
+ * Created by lgoedhart on 10/05/2016.
+ */
+public class DeviceInfoResponseCommandMessage extends MedtronicResponseMessage {
+    private String serial = "";
+    private final Pattern pattern = Pattern.compile(".*?\\^(\\d{4}-\\d{7})\\^.*");
+
+    protected DeviceInfoResponseCommandMessage(MedtronicCnlSession pumpSession, byte[] payload)
+            throws ChecksumException, EncryptionException, TimeoutException, UnexpectedMessageException, IOException {
+        super(pumpSession, payload);
+
+        extractStickSerial(new String(payload));
+    }
+
+    public String getSerial() {
+        return serial;
+    }
+
+    private void extractStickSerial(String astmMessage) {
+        Matcher matcher = pattern.matcher(astmMessage);
+        if (matcher.find()) {
+            serial = matcher.group(1);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java
index 87eaf9f20fd82c03383a8f7408a03fa794d7bfb2..10f4d26e0af48ee6035450bd17cd0e1bf8c1fce1 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoResponseMessage.java
@@ -22,10 +22,6 @@ public class ReadInfoResponseMessage extends MedtronicResponseMessage {
         pumpMAC = infoBuffer.getLong(8);
     }
 
-    public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException {
-        return new ReadInfoResponseMessage(pumpSession, bytes);
-    }
-
     public long getLinkMAC() {
         return linkMAC;
     }
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java
index 8bb77ad63f543c992a1afbee43760462ad23cdec..8481a169404e89a2edb3025c516ef3f38d426e3b 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyResponseMessage.java
@@ -22,15 +22,6 @@ public class RequestLinkKeyResponseMessage extends MedtronicResponseMessage {
         setPackedLinkKey(infoBuffer.array());
     }
 
-    public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException {
-        // TODO - turn this into a factory
-        ContourNextLinkMessage message = MedtronicResponseMessage.fromBytes(pumpSession, bytes);
-
-        // TODO - Validate the MessageType
-
-        return message;
-    }
-
     public byte[] getKey() {
         return key;
     }
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..1e6dad6b23df39893aba22f2424990c833106cf5 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
@@ -25,10 +25,10 @@ import info.nightscout.android.R;
 import info.nightscout.android.USB.UsbHidDriver;
 import info.nightscout.android.medtronic.MainActivity;
 import info.nightscout.android.medtronic.MedtronicCnlReader;
-import info.nightscout.android.medtronic.message.ChecksumException;
-import info.nightscout.android.medtronic.message.EncryptionException;
+import info.nightscout.android.medtronic.message.exception.ChecksumException;
+import info.nightscout.android.medtronic.message.exception.EncryptionException;
 import info.nightscout.android.medtronic.message.MessageUtils;
-import info.nightscout.android.medtronic.message.UnexpectedMessageException;
+import info.nightscout.android.medtronic.message.exception.UnexpectedMessageException;
 import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo;
 import info.nightscout.android.model.medtronicNg.PumpInfo;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;