diff --git a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
index 9c632ee91d22a1c65128f9215a2e42ae3eb1c11c..f73e3ab923c5960483afd1e14d839d8612435ec8 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
@@ -15,6 +15,7 @@ import android.hardware.usb.UsbManager;
 import android.os.BatteryManager;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.preference.PreferenceManager;
 import android.support.v4.app.TaskStackBuilder;
 import android.support.v4.content.LocalBroadcastManager;
@@ -32,7 +33,8 @@ import android.view.View;
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
 
-import com.github.mikephil.charting.data.realm.implementation.RealmLineData;
+import com.github.mikephil.charting.charts.LineChart;
+import com.github.mikephil.charting.data.LineData;
 import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet;
 import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
 import com.github.mikephil.charting.utils.ColorTemplate;
@@ -52,9 +54,11 @@ import info.nightscout.android.R;
 import info.nightscout.android.USB.UsbHidDriver;
 import info.nightscout.android.eula.Eula;
 import info.nightscout.android.eula.Eula.OnEulaAgreedTo;
+import info.nightscout.android.medtronic.service.MedtronicCnlAlarmReceiver;
 import info.nightscout.android.medtronic.service.MedtronicCnlIntentService;
 import info.nightscout.android.model.CgmStatusEvent;
 import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo;
+import info.nightscout.android.model.medtronicNg.PumpInfo;
 import info.nightscout.android.settings.SettingsActivity;
 import info.nightscout.android.upload.MedtronicNG.PumpStatusRecord;
 import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService;
@@ -63,28 +67,32 @@ import io.realm.RealmResults;
 import io.realm.Sort;
 import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
 
-/* Main activity for the MainActivity program */
 public class MainActivity extends AppCompatActivity implements OnSharedPreferenceChangeListener, OnEulaAgreedTo {
     private static final String TAG = MainActivity.class.getSimpleName();
 
     public static int batLevel = 0;
     public static PumpStatusRecord pumpStatusRecord = new PumpStatusRecord();
+    private static long activePumpMac;
     boolean mEnableCgmService = true;
     SharedPreferences prefs = null;
+    private PumpInfo mActivePump;
     private TextView mTextViewLog; // This will eventually move to a status page.
-    private Intent mCnlIntentService;
+    private LineChart mChart;
     private Intent mNightscoutUploadService;
     private Handler mUiRefreshHandler = new Handler();
     private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable();
     private Realm mRealm;
 
+    public static void setActivePumpMac(long pumpMac) {
+        activePumpMac = pumpMac;
+    }
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         Log.i(TAG, "onCreate called");
         super.onCreate(savedInstanceState);
 
         mRealm = Realm.getDefaultInstance();
-        mCnlIntentService = new Intent(this, MedtronicCnlIntentService.class);
         mNightscoutUploadService = new Intent(this, NightscoutUploadIntentService.class);
 
         setContentView(R.layout.activity_main);
@@ -186,7 +194,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                         } else if (drawerItem.equals(itemGetNow)) {
                             startCgmService();
                         } else if (drawerItem.equals(itemClearLog)) {
-                            mTextViewLog.setText("", BufferType.EDITABLE);
+                            clearLogText();
                         }
 
                         return false;
@@ -195,6 +203,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                 .build();
 
         mTextViewLog = (TextView) findViewById(R.id.textview_log);
+        mChart = (LineChart) findViewById(R.id.chart);
     }
 
     @Override
@@ -276,6 +285,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         startDisplayRefreshLoop();
     }
 
+    private void clearLogText() {
+        mTextViewLog.setText("", BufferType.EDITABLE);
+    }
+
     private void startDisplayRefreshLoop() {
         mUiRefreshHandler.post(mUiRefreshRunnable);
     }
@@ -288,35 +301,26 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         startCgmService(0L);
     }
 
-    private void startCgmService(long runAtTime) {
+    private void startCgmService(long initialPoll) {
         Log.i(TAG, "startCgmService called");
 
         if (!mEnableCgmService) {
             return;
         }
 
-        if (runAtTime == 0L) {
-            startService(mCnlIntentService);
-        } else {
-            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-            PendingIntent pending = PendingIntent.getService(this, 0, mCnlIntentService, 0);
-
-            alarmManager.set(AlarmManager.RTC_WAKEUP, runAtTime, pending);
+        if (initialPoll == 0) {
+            initialPoll = SystemClock.currentThreadTimeMillis();
         }
-    }
-
-    private void startCgmServicePolling(long initialPoll) {
-        Log.i(TAG, "startCgmServicePolling called");
 
-        if (!mEnableCgmService) {
-            return;
-        }
+        Log.d(TAG, "startCgmService set to fire at " + new Date(initialPoll));
+        clearLogText();
 
         // Cancel any existing polling.
         stopCgmService();
 
         AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-        PendingIntent pending = PendingIntent.getService(this, 0, mCnlIntentService, 0);
+        Intent receiverIntent = new Intent(this, MedtronicCnlAlarmReceiver.class);
+        PendingIntent pending = PendingIntent.getBroadcast(this, 0, receiverIntent, 0);
 
         alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                 initialPoll, MedtronicCnlIntentService.POLL_PERIOD_MS, pending);
@@ -330,7 +334,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         Log.i(TAG, "stopCgmService called");
 
         AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-        PendingIntent pending = PendingIntent.getService(this, 0, mCnlIntentService, 0);
+        Intent receiverIntent = new Intent(this, MedtronicCnlAlarmReceiver.class);
+        PendingIntent pending = PendingIntent.getBroadcast(this, 0, receiverIntent, 0);
 
         alarmManager.cancel(pending);
     }
@@ -369,15 +374,16 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     @Override
     protected void onDestroy() {
         Log.i(TAG, "onDestroy called");
+        super.onDestroy();
+
         PreferenceManager.getDefaultSharedPreferences(getBaseContext()).unregisterOnSharedPreferenceChangeListener(this);
         cancelDisplayRefreshLoop();
 
+        mRealm.close();
+
         if (!mEnableCgmService) {
             stopCgmService();
         }
-
-        mRealm.close();
-        super.onDestroy();
     }
 
     @Override
@@ -439,6 +445,23 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         }
     }
 
+    private PumpInfo getActivePump() {
+        if (activePumpMac != 0L && (mActivePump == null || !mActivePump.isValid() || mActivePump.getPumpMac() != activePumpMac)) {
+            mActivePump = null;
+
+            PumpInfo pump = mRealm
+                    .where(PumpInfo.class)
+                    .equalTo("pumpMac", MainActivity.activePumpMac)
+                    .findFirst();
+
+            if (pump != null & pump.isValid()) {
+                mActivePump = pump;
+            }
+        }
+
+        return mActivePump;
+    }
+
     private class StatusMessageReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -463,7 +486,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
             }
             TextView textViewTrend = (TextView) findViewById(R.id.textview_trend);
             TextView textViewIOB = (TextView) findViewById(R.id.textview_iob);
-            //LineChart chart = (LineChart) findViewById(R.id.chart);
 
             // Get the most recently written CGM record.
             RealmResults<CgmStatusEvent> results =
@@ -505,17 +527,28 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
             textViewTrend.setText(Html.fromHtml(renderTrendHtml(cgmRecord.getTrend())));
             textViewIOB.setText(String.format(Locale.getDefault(), "%.2f", pumpStatusRecord.activeInsulin));
 
+            /*
+            // Open Realm because we're in a different thread
+            Realm realm = Realm.getDefaultInstance();
+            if (MainActivity.mActivePump != null && MainActivity.mActivePump.isValid()) {
+                PumpInfo pump = MainActivity.mActivePump;
+                long pumpMac = pump.getPumpMac();
+                CgmStatusEvent cgmData = MainActivity.mActivePump.getCgmHistory().last();
+            }
+            realm.close();
+            */
+
             // TODO - waiting for MPAndroidCharts 3.0.0. This will fix:
             // Date support
             // Realm v1.0.0 support
-            // updateChart(results);
+            //updateChart(results);
 
             // Run myself again in 60 seconds;
             mUiRefreshHandler.postDelayed(this, 60000L);
         }
 
         private void updateChart(RealmResults<CgmStatusEvent> results) {
-            RealmLineDataSet<CgmStatusEvent> lineDataSet = new RealmLineDataSet<>(results, "sgv", "eventDate");
+            RealmLineDataSet<CgmStatusEvent> lineDataSet = new RealmLineDataSet<>(results, "eventDate", "sgv");
 
             lineDataSet.setDrawCircleHole(false);
             lineDataSet.setColor(ColorTemplate.rgb("#FF5722"));
@@ -526,11 +559,11 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
             ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
             dataSets.add(lineDataSet);
 
-            RealmLineData lineData = new RealmLineData(results, "eventDate", dataSets);
+            LineData lineData = new LineData(dataSets);
 
             // set data
-            //chart.setMinimumHeight(200);
-            //chart.setData(lineData);
+            mChart.setMinimumHeight(200);
+            mChart.setData(lineData);
         }
     }
 
@@ -538,12 +571,31 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
         @Override
         public void onReceive(Context context, Intent intent) {
+            // If the MainActivity has already been destroyed (meaning the Realm instance has been closed)
+            // then don't worry about processing this broadcast
+            if (mRealm.isClosed()) {
+                return;
+            }
+
+            CgmStatusEvent cgmData = null;
+
+            PumpInfo pump = getActivePump();
+
+            if (pump != null & pump.isValid()) {
+                long pumpMac = pump.getPumpMac();
+                cgmData = pump.getCgmHistory().last();
+            }
+
+            if (cgmData != null) {
+                Log.d(TAG, "It's working yo");
+            }
+
             CgmStatusEvent record = mRealm.where(CgmStatusEvent.class)
                     .findAll()
                     .last();
 
             long nextPoll = record.getEventDate().getTime() + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS + MedtronicCnlIntentService.POLL_PERIOD_MS;
-            startCgmServicePolling(nextPoll);
+            startCgmService(nextPoll);
             Log.d(TAG, "Next Poll at " + new Date(nextPoll).toString());
 
             // Delete invalid or old records from Realm
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 8b56ea37e359278c03f25173894a2bd12f9b5ea0..acd660b2421edb898df25d44174d3d30876992e5 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCNLReader.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCNLReader.java
@@ -2,11 +2,15 @@ package info.nightscout.android.medtronic;
 
 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.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Locale;
 import java.util.concurrent.TimeoutException;
@@ -31,16 +35,15 @@ import info.nightscout.android.medtronic.message.PumpTimeRequestMessage;
 import info.nightscout.android.medtronic.message.PumpTimeResponseMessage;
 import info.nightscout.android.medtronic.message.ReadInfoResponseMessage;
 import info.nightscout.android.medtronic.message.UnexpectedMessageException;
-import info.nightscout.android.medtronic.service.MedtronicCnlIntentService;
 import info.nightscout.android.model.CgmStatusEvent;
 import info.nightscout.android.utils.HexDump;
 
 /**
  * Created by lgoedhart on 24/03/2016.
  */
-public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
+public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
 
-    private static final String TAG = MedtronicCnlIntentService.class.getSimpleName();
+    private static final String TAG = MedtronicCnlReader.class.getSimpleName();
 
     private static final int USB_BLOCKSIZE = 64;
     private static final int READ_TIMEOUT_MS = 5000;
@@ -53,10 +56,31 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
 
     private String mStickSerial = null;
 
-    public MedtronicCNLReader(UsbHidDriver device) {
+    public MedtronicCnlReader(UsbHidDriver device) {
         mDevice = device;
     }
 
+    private static CgmStatusEvent.TREND fromMessageByte(byte messageByte) {
+        switch (messageByte) {
+            case (byte) 0x60:
+                return CgmStatusEvent.TREND.FLAT;
+            case (byte) 0xc0:
+                return CgmStatusEvent.TREND.DOUBLE_UP;
+            case (byte) 0xa0:
+                return CgmStatusEvent.TREND.SINGLE_UP;
+            case (byte) 0x80:
+                return CgmStatusEvent.TREND.FOURTY_FIVE_UP;
+            case (byte) 0x40:
+                return CgmStatusEvent.TREND.FOURTY_FIVE_DOWN;
+            case (byte) 0x20:
+                return CgmStatusEvent.TREND.SINGLE_DOWN;
+            case (byte) 0x00:
+                return CgmStatusEvent.TREND.DOUBLE_DOWN;
+            default:
+                return CgmStatusEvent.TREND.NOT_COMPUTABLE;
+        }
+    }
+
     public String getStickSerial() {
         return mStickSerial;
     }
@@ -70,28 +94,28 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
 
         byte[] responseBuffer = new byte[USB_BLOCKSIZE];
         int bytesRead;
-        int messageSize;
+        int messageSize = 0;
 
         do {
             bytesRead = mDevice.read(responseBuffer, READ_TIMEOUT_MS);
 
-            if (bytesRead == 0) {
+            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);
 
-            // 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);
-        } while (bytesRead > 0 && (messageSize + 4) == bytesRead);
-        // TODO - how to deal with messages that finish on the boundary?
-
-        // FIXME - remove debugging
         String responseString = HexDump.dumpHexString(responseMessage.toByteArray());
         Log.d(TAG, "READ: " + responseString);
 
@@ -182,27 +206,6 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
         }
     }
 
-    private static CgmStatusEvent.TREND fromMessageByte(byte messageByte) {
-        switch( messageByte ) {
-            case (byte) 0x60:
-                return CgmStatusEvent.TREND.FLAT;
-            case (byte) 0xc0:
-                return CgmStatusEvent.TREND.DOUBLE_UP;
-            case (byte) 0xa0:
-                return CgmStatusEvent.TREND.SINGLE_UP;
-            case (byte) 0x80:
-                return CgmStatusEvent.TREND.FOURTY_FIVE_UP;
-            case (byte) 0x40:
-                return CgmStatusEvent.TREND.FOURTY_FIVE_DOWN;
-            case (byte) 0x20:
-                return CgmStatusEvent.TREND.SINGLE_DOWN;
-            case (byte) 0x00:
-                return CgmStatusEvent.TREND.DOUBLE_DOWN;
-            default:
-                return CgmStatusEvent.TREND.NOT_COMPUTABLE;
-        }
-    }
-
     public void enterControlMode() throws IOException, TimeoutException, UnexpectedMessageException {
         boolean doRetry = false;
 
@@ -223,21 +226,26 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
     }
 
     public void enterPassthroughMode() throws IOException, TimeoutException, UnexpectedMessageException {
+        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);
+        Log.d(TAG, "Finished enterPasshtroughMode");
     }
 
     public void openConnection() throws IOException, TimeoutException {
+        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();
+        Log.d(TAG, "Finished openConnection");
     }
 
     public void requestReadInfo() throws IOException, TimeoutException, EncryptionException, ChecksumException {
+        Log.d(TAG, "Begin requestReadInfo");
         new ContourNextLinkBinaryMessage(ContourNextLinkBinaryMessage.CommandType.READ_INFO, mPumpSession, null).send(this);
 
         ContourNextLinkMessage response = ReadInfoResponseMessage.fromBytes(mPumpSession, readMessage());
@@ -251,19 +259,36 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
 
         this.getPumpSession().setLinkMAC(linkMAC);
         this.getPumpSession().setPumpMAC(pumpMAC);
+        Log.d(TAG, String.format("Finished requestReadInfo. linkMAC = '%d', pumpMAC = '%d", linkMAC, pumpMAC));
     }
 
-    public byte negotiateChannel() throws IOException, ChecksumException, TimeoutException {
-        for (byte channel : RADIO_CHANNELS) {
+    public byte negotiateChannel(byte lastRadioChannel) throws IOException, ChecksumException, TimeoutException {
+        ArrayList<Byte> radioChannels = new ArrayList<>(Arrays.asList(ArrayUtils.toObject(RADIO_CHANNELS)));
+
+        if (lastRadioChannel != 0x00) {
+            // If we know the last channel that was used, shuffle the negotiation order
+            Byte lastChannel = radioChannels.remove(radioChannels.indexOf(new Byte(lastRadioChannel)));
+
+            if (lastChannel != null) {
+                radioChannels.add(0, lastChannel);
+            }
+        }
+
+        Log.d(TAG, "Begin negotiateChannel");
+        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()) {
@@ -276,16 +301,20 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
             }
         }
 
+        Log.d(TAG, String.format("Finished negotiateChannel with channel '%d'", mPumpSession.getRadioChannel()));
         return mPumpSession.getRadioChannel();
     }
 
     public void beginEHSMSession() throws EncryptionException, IOException, TimeoutException {
+        Log.d(TAG, "Begin beginEHSMSession");
         new BeginEHSMMessage(mPumpSession).send(this);
         // The Begin EHSM Session only has an 0x81 response
         readMessage();
+        Log.d(TAG, "Finished beginEHSMSession");
     }
 
     public Date getPumpTime() throws EncryptionException, IOException, ChecksumException, TimeoutException {
+        Log.d(TAG, "Begin getPumpTime");
         // FIXME - throw if not in EHSM mode (add a state machine)
         Date timeAtCapture = new Date();
 
@@ -296,8 +325,10 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
         // Read the 0x80
         ContourNextLinkMessage response = PumpTimeResponseMessage.fromBytes(mPumpSession, readMessage());
 
-        if (response.encode().length < 57) {
+        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();
         }
 
@@ -308,10 +339,12 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
         long rtc = dateBuffer.getInt(0) & 0x00000000ffffffffL;
         long offset = dateBuffer.getInt(4);
 
+        Log.d(TAG, "Finished getPumpTime with date " + MessageUtils.decodeDateTime(rtc, offset));
         return MessageUtils.decodeDateTime(rtc, offset);
     }
 
     public void getPumpStatus(CgmStatusEvent cgmRecord, 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);
@@ -321,8 +354,10 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
         // Read the 0x80
         ContourNextLinkMessage response = PumpStatusResponseMessage.fromBytes(mPumpSession, readMessage());
 
-        if (response.encode().length < 57) {
+        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;
         }
 
@@ -354,32 +389,42 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler {
         long rawReservoirAmount = statusBuffer.getInt(0x2b);
         MainActivity.pumpStatusRecord.reservoirAmount = new BigDecimal(rawReservoirAmount / 10000f).setScale(3, BigDecimal.ROUND_HALF_UP);
         MainActivity.pumpStatusRecord.batteryPercentage = (statusBuffer.get(0x2a));
+
+        Log.d(TAG, "Finished getPumpStatus");
     }
 
     public void endEHSMSession() throws EncryptionException, IOException, TimeoutException {
+        Log.d(TAG, "Begin endEHSMSession");
         new EndEHSMMessage(mPumpSession).send(this);
         // The End EHSM Session only has an 0x81 response
         readMessage();
+        Log.d(TAG, "Finished endEHSMSession");
     }
 
     public void closeConnection() throws IOException, TimeoutException {
+        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();
+        Log.d(TAG, "Finished closeConnection");
     }
 
     public void endPassthroughMode() throws IOException, TimeoutException, UnexpectedMessageException {
+        Log.d(TAG, "Begin endPassthroughMode");
         new ContourNextLinkCommandMessage("W|").send(this);
         checkControlMessage(readMessage(), ASCII.ACK.value);
         new ContourNextLinkCommandMessage("Q|").send(this);
         checkControlMessage(readMessage(), ASCII.ACK.value);
         new ContourNextLinkCommandMessage("0|").send(this);
         checkControlMessage(readMessage(), ASCII.ACK.value);
+        Log.d(TAG, "Finished endPassthroughMode");
     }
 
     public void endControlMode() throws IOException, TimeoutException, UnexpectedMessageException {
+        Log.d(TAG, "Begin endControlMode");
         new ContourNextLinkCommandMessage(ASCII.EOT.value).send(this);
         checkControlMessage(readMessage(), ASCII.ENQ.value);
+        Log.d(TAG, "Finished endControlMode");
     }
 
     public enum ASCII {
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 1f773efbdfa5e3430cce9e277c412ba3c9487765..33eda925bd298ff4079372cf0189bfc82c1e1d83 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
@@ -48,7 +48,7 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage{
 
         payloadBuffer.put((byte) 0x51);
         payloadBuffer.put((byte) 0x3);
-        payloadBuffer.put("000000".getBytes()); // Text of Pump serial, but 000000 for 640g
+        payloadBuffer.put("000000".getBytes()); // Text of PumpInfo serial, but 000000 for 640g
         byte[] unknownBytes = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
         payloadBuffer.put(unknownBytes);
         payloadBuffer.put(commandType.value);
diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0d4a41c68b561a7961e63637379f42c567257c9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java
@@ -0,0 +1,21 @@
+package info.nightscout.android.medtronic.service;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.content.WakefulBroadcastReceiver;
+import android.util.Log;
+
+/**
+ * Created by lgoedhart on 14/07/2016.
+ */
+public class MedtronicCnlAlarmReceiver extends WakefulBroadcastReceiver {
+    private static final String TAG = MedtronicCnlAlarmReceiver.class.getSimpleName();
+
+    @Override
+    public void onReceive(final Context context, Intent intent) {
+        // Start the IntentService
+        Log.d(TAG, "Received broadcast message");
+        Intent service = new Intent(context, MedtronicCnlIntentService.class);
+        startWakefulService(context, service);
+    }
+}
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 d39f3246dadb395b61d450476ec7e65335f8eca8..f7385e9dac858b8b7ad4aa962757b92d23d57e56 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
@@ -17,13 +17,15 @@ import java.util.concurrent.TimeoutException;
 
 import info.nightscout.android.USB.UsbHidDriver;
 import info.nightscout.android.medtronic.MainActivity;
-import info.nightscout.android.medtronic.MedtronicCNLReader;
+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.MessageUtils;
 import info.nightscout.android.medtronic.message.UnexpectedMessageException;
 import info.nightscout.android.model.CgmStatusEvent;
 import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo;
+import info.nightscout.android.model.medtronicNg.PumpInfo;
+import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
 import io.realm.Realm;
 import io.realm.RealmResults;
 
@@ -89,7 +91,9 @@ public class MedtronicCnlIntentService extends IntentService {
 
         if (!hasUsbHostFeature()) {
             sendStatus("It appears that this device doesn't support USB OTG.");
-            Log.w(TAG, "Device does not support USB OTG");
+            Log.e(TAG, "Device does not support USB OTG");
+            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+            // TODO - throw, don't return
             return;
         }
 
@@ -97,26 +101,31 @@ public class MedtronicCnlIntentService extends IntentService {
         if (cnlStick == null) {
             sendStatus("USB connection error. Is the Bayer Contour Next Link plugged in?");
             Log.w(TAG, "USB connection error. Is the CNL plugged in?");
+            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+            // TODO - throw, don't return
             return;
         }
 
         if (!mUsbManager.hasPermission(UsbHidDriver.getUsbDevice(mUsbManager, USB_VID, USB_PID))) {
             sendMessage(Constants.ACTION_NO_USB_PERMISSION);
+            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+            // TODO - throw, don't return
             return;
         }
         mHidDevice = UsbHidDriver.acquire(mUsbManager, cnlStick);
 
-        Realm realm = Realm.getDefaultInstance();
-
         try {
             mHidDevice.open();
         } catch (Exception e) {
             Log.e(TAG, "Unable to open serial device", e);
+            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+            // TODO - throw, don't return
             return;
         }
 
-        MedtronicCNLReader cnlReader = new MedtronicCNLReader(mHidDevice);
+        MedtronicCnlReader cnlReader = new MedtronicCnlReader(mHidDevice);
 
+        Realm realm = Realm.getDefaultInstance();
         realm.beginTransaction();
 
         try {
@@ -131,6 +140,7 @@ public class MedtronicCnlIntentService extends IntentService {
                     .findFirst();
 
             if (info == null) {
+                // TODO - use realm.createObject()?
                 info = new ContourNextLinkInfo();
                 info.setSerialNumber(cnlReader.getStickSerial());
 
@@ -145,6 +155,9 @@ public class MedtronicCnlIntentService extends IntentService {
                 realm.commitTransaction();
 
                 sendMessage(Constants.ACTION_USB_REGISTER);
+                realm.close();
+                MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+                // TODO - throw, don't return
                 return;
             }
 
@@ -157,11 +170,26 @@ public class MedtronicCnlIntentService extends IntentService {
                 cnlReader.enterPassthroughMode();
                 cnlReader.openConnection();
                 cnlReader.requestReadInfo();
-                byte radioChannel = cnlReader.negotiateChannel();
+
+                long pumpMAC = cnlReader.getPumpSession().getPumpMAC();
+                Log.i(TAG, "PumpInfo MAC: " + (pumpMAC & 0xffffff));
+                MainActivity.setActivePumpMac(pumpMAC);
+                PumpInfo activePump = realm
+                        .where(PumpInfo.class)
+                        .equalTo("pumpMac", pumpMAC)
+                        .findFirst();
+
+                if (activePump == null) {
+                    activePump = realm.createObject(PumpInfo.class);
+                    activePump.setPumpMac(pumpMAC);
+                }
+
+                byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel());
                 if (radioChannel == 0) {
                     sendStatus("Could not communicate with the 640g. Are you near the pump?");
                     Log.i(TAG, "Could not communicate with the 640g. Are you near the pump?");
                 } else {
+                    activePump.setLastRadioChannel(radioChannel);
                     sendStatus(String.format(Locale.getDefault(), "Connected to Contour Next Link on channel %d.", (int) radioChannel));
                     Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel));
                     cnlReader.beginEHSMSession();
@@ -170,27 +198,33 @@ public class MedtronicCnlIntentService extends IntentService {
                     CgmStatusEvent cgmRecord = realm.createObject(CgmStatusEvent.class);
 
                     String deviceName = String.format("medtronic-640g://%s", cnlReader.getStickSerial());
+                    activePump.setDeviceName(deviceName);
+
+                    // TODO - this should not be necessary. We should reverse lookup the device name from PumpInfo
                     cgmRecord.setDeviceName(deviceName);
                     //pumpRecord.setDeviceName(deviceName);
+
                     // TODO - legacy. Remove once we've plumbed in pumpRecord.
-                    MainActivity.pumpStatusRecord.setDeviceName(deviceName);
+                    //MainActivity.pumpStatusRecord.setDeviceName(deviceName);
 
-                    //pumpRecord.setPumpDate(cnlReader.getPumpTime());
                     long pumpTime = cnlReader.getPumpTime().getTime();
                     long pumpOffset = pumpTime - System.currentTimeMillis();
+
                     // TODO - send ACTION to MainActivity to show offset between pump and uploader.
                     MainActivity.pumpStatusRecord.pumpDate = new Date(pumpTime - pumpOffset);
+                    //pumpRecord.setPumpDate(cnlReader.getPumpTime());
+                    cgmRecord.setPumpDate(new Date(pumpTime - pumpOffset));
                     cnlReader.getPumpStatus(cgmRecord, pumpOffset);
+                    activePump.getCgmHistory().add(cgmRecord);
 
                     cnlReader.endEHSMSession();
 
                     boolean cancelTransaction = true;
                     if (cgmRecord.getSgv() != 0) {
                         // Check that the record doesn't already exist before committing
-                        RealmResults<CgmStatusEvent> checkExistingRecords = realm
-                                .where(CgmStatusEvent.class)
+                        RealmResults<CgmStatusEvent> checkExistingRecords = activePump.getCgmHistory()
+                                .where()
                                 .equalTo("eventDate", cgmRecord.getEventDate())
-                                .equalTo("deviceName", cgmRecord.getDeviceName())
                                 .equalTo("sgv", cgmRecord.getSgv())
                                 .findAll();
 
@@ -233,13 +267,16 @@ public class MedtronicCnlIntentService extends IntentService {
             Log.e(TAG, "Could not close connection.", e);
             sendStatus("Could not close connection: " + e.getMessage());
         } finally {
-            if (realm.isInTransaction()) {
-                // If we didn't commit the transaction, we've run into an error. Let's roll it back
-                realm.cancelTransaction();
+            if (!realm.isClosed()) {
+                if (realm.isInTransaction()) {
+                    // If we didn't commit the transaction, we've run into an error. Let's roll it back
+                    realm.cancelTransaction();
+                }
+                realm.close();
             }
-        }
 
-        realm.close();
+            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+        }
     }
 
     private boolean hasUsbHostFeature() {