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 82e3026de27326a6e6bf9a294eb1ee731697992c..75680ee06afa525abb098fc0e48cad44f539fd0d 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
@@ -70,7 +70,6 @@ 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.MedtronicCnlAlarmManager;
-import info.nightscout.android.medtronic.service.MedtronicCnlAlarmReceiver;
 import info.nightscout.android.medtronic.service.MedtronicCnlIntentService;
 import info.nightscout.android.model.medtronicNg.PumpInfo;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
@@ -93,7 +92,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
     private int chartZoom = 3;
     private boolean hasZoomedChart = false;
-    private NumberFormat sgvFormatter;
 
     private boolean mEnableCgmService = true;
     private SharedPreferences prefs = null;
@@ -104,7 +102,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable();
     private Realm mRealm;
     private StatusMessageReceiver statusMessageReceiver = new StatusMessageReceiver();
-    private MedtronicCnlAlarmReceiver medtronicCnlAlarmReceiver = new MedtronicCnlAlarmReceiver();
 
     /**
      * calculate the next poll timestamp based on last svg event
@@ -167,15 +164,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         configurationStore.setMmolxl(prefs.getBoolean("mmolxl", false));
         configurationStore.setMmolxlDecimals(prefs.getBoolean("mmolDecimals", false));
 
-        if (configurationStore.isMmolxl()) {
-            if (configurationStore.isMmolxlDecimals())
-                sgvFormatter = new DecimalFormat("0.00");
-            else
-                sgvFormatter = new DecimalFormat("0.0");
-        } else {
-            sgvFormatter = new DecimalFormat("0");
-        }
-
         // Disable battery optimization to avoid missing values on 6.0+
         // taken from https://github.com/NightscoutFoundation/xDrip/blob/master/app/src/main/java/com/eveningoutpost/dexdrip/Home.java#L277L298
 
@@ -559,14 +547,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         } else if (key.equals("mmolxl") || key.equals("mmolDecimals")) {
             configurationStore.setMmolxl(sharedPreferences.getBoolean("mmolxl", false));
             configurationStore.setMmolxlDecimals(sharedPreferences.getBoolean("mmolDecimals", false));
-            if (configurationStore.isMmolxl()) {
-                if (configurationStore.isMmolxlDecimals())
-                    sgvFormatter = new DecimalFormat("0.00");
-                else
-                    sgvFormatter = new DecimalFormat("0.0");
-            } else {
-                sgvFormatter = new DecimalFormat("0");
-            }
             refreshDisplay();
         } else if (key.equals("pollInterval")) {
             configurationStore.setPollInterval(Long.parseLong(sharedPreferences.getString("pollInterval",
@@ -944,6 +924,9 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     private class UsbReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
+            // TODO move this somewhere else ... wherever it belongs
+            // realm might be closed ... sometimes occurs when USB is disconnected and replugged ...
+            if (mRealm.isClosed()) mRealm = Realm.getDefaultInstance();
             String action = intent.getAction();
             if (MedtronicCnlIntentService.Constants.ACTION_USB_PERMISSION.equals(action)) {
                 boolean permissionGranted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java
index 358cc203123e64d456f05c97cd116eb33e3af9a2..b58d702ce647bf2c1014af714954c15107661788 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java
@@ -16,11 +16,10 @@ import info.nightscout.android.utils.ConfigurationStore;
  */
 public class MedtronicCnlAlarmManager {
     private static final String TAG = MedtronicCnlAlarmManager.class.getSimpleName();
-    private static final int ALARM_ID = 102; // Alarm id
+    private static final int ALARM_ID = 102;
 
     private static PendingIntent pendingIntent = null;
     private static AlarmManager alarmManager = null;
-    private static long nextAlarm = Long.MAX_VALUE;
 
     public static void setContext(Context context) {
         cancelAlarm();
@@ -30,11 +29,6 @@ public class MedtronicCnlAlarmManager {
         pendingIntent = PendingIntent.getBroadcast(context, ALARM_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
-    // Setting the alarm in 15 seconds from now
-    public static void setAlarm() {
-        setAlarm(System.currentTimeMillis());
-    }
-
     /**
      * set the alarm in the future
      *
@@ -44,7 +38,7 @@ public class MedtronicCnlAlarmManager {
         setAlarm(System.currentTimeMillis() + inFuture);
     }
 
-    // Setting the alarm to call onRecieve
+    // Setting the alarm to call onReceive
     public static void setAlarm(long millis) {
         if (alarmManager == null || pendingIntent == null)
             return;
@@ -56,21 +50,14 @@ public class MedtronicCnlAlarmManager {
         if (millis < now)
             millis = now;
 
-        // only accept alarm nearer than the last one
-        //if (nextAlarm < millis && nextAlarm > now) {
-        //    return;
-        //}
-
         cancelAlarm();
 
-        nextAlarm = millis;
-
         Log.d(TAG, "Alarm set to fire at " + new Date(millis));
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(millis, null), pendingIntent);
         } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
             // Android 5.0.0 + 5.0.1 (e.g. Galaxy S4) has a bug.
-            // Alarms are not exact. Fixed in 5.0.2 oder CM12
+            // Alarms are not exact. Fixed in 5.0.2 and CM12
             alarmManager.setExact(AlarmManager.RTC_WAKEUP, millis, pendingIntent);
         } else {
             alarmManager.set(AlarmManager.RTC_WAKEUP, millis, pendingIntent);
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 9b46b76a7c1261f278ce403d497c7495e08c24da..327895b86d96e6582f240f497c7c2c5765bb6532 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
@@ -57,6 +57,8 @@ public class MedtronicCnlIntentService extends IntentService {
     private UsbManager mUsbManager;
     private DataStore dataStore = DataStore.getInstance();
     private ConfigurationStore configurationStore = ConfigurationStore.getInstance();
+    private DateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss", Locale.US);
+
 
     public MedtronicCnlIntentService() {
         super(MedtronicCnlIntentService.class.getName());
@@ -104,159 +106,136 @@ public class MedtronicCnlIntentService extends IntentService {
 
     protected void onHandleIntent(Intent intent) {
         Log.d(TAG, "onHandleIntent called");
+        try {
+            // TODO use of ConfigurationStore is confusinng if pollInterval uses the CS, which
+            // uses the POLL_PERIOD_MS, while the latter constant is also used directly.
+
+            // Note that the variable pollInterval refers to the poll we'd like to make to the pump,
+            // based on settings and battery level, while POLL_PERIOD_MS is used to calculate
+            // when the pump is going to poll data from the transmitter again.
+            // Thus POLL_PERIOD_MS is important to calculate times we'd be clashing with transmitter
+            // to pump transmissions, which are then checked against the time the uploader would
+            // like to poll, which is calculated using the pollInterval variable.
+            // TODO find better variable names to make this distinction clearer and/or if possible
+            // do more method extraction refactorings to make this method easier to grasp
+
+            final long timePollStarted = System.currentTimeMillis();
+            final long timeLastGoodSGV = dataStore.getLastPumpStatus().getSgvDate().getTime();
+
+            final long timePollExpected;
+            if (timeLastGoodSGV != 0) {
+                timePollExpected = timeLastGoodSGV + POLL_PERIOD_MS + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((timePollStarted - 1000L - (timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
+            } else {
+                timePollExpected = timePollStarted;
+            }
 
-        long timePollStarted = System.currentTimeMillis(),
-                timePollExpected = timePollStarted,
-                timeLastGoodSGV = dataStore.getLastPumpStatus().getEventDate().getTime();
-
-        short pumpBatteryLevel = dataStore.getLastPumpStatus().getBatteryPercentage();
-
-        if (timeLastGoodSGV != 0) {
-            timePollExpected = timeLastGoodSGV + POLL_PERIOD_MS + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((timePollStarted - 1000L - (timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
-        }
-
-        // avoid polling when too close to sensor-pump comms
-        if (((timePollExpected - timePollStarted) > 5000L) && ((timePollExpected - timePollStarted) < (POLL_GRACE_PERIOD_MS + 45000L))) {
-            sendStatus("Please wait: Poll due in " + ((timePollExpected - timePollStarted) / 1000L) + " seconds");
-            MedtronicCnlAlarmManager.setAlarm(timePollExpected);
-            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
-            return;
-        }
-
-        long pollInterval = configurationStore.getPollInterval();
-        if ((pumpBatteryLevel > 0) && (pumpBatteryLevel <= 25)) {
-            pollInterval = configurationStore.getLowBatteryPollInterval();
-        }
-
-        if (!hasUsbHostFeature()) {
-            sendStatus("It appears that this device doesn't support USB OTG.");
-            Log.e(TAG, "Device does not support USB OTG");
-            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
-            // TODO - throw, don't return
-            return;
-        }
-
-        UsbDevice cnlStick = UsbHidDriver.getUsbDevice(mUsbManager, USB_VID, USB_PID);
-        if (cnlStick == null) {
-            sendStatus("USB connection error. Is the Contour Next Link plugged in?");
-            Log.w(TAG, "USB connection error. Is the CNL plugged in?");
-
-            // TODO - set status if offline or Nightscout not reachable
-            uploadToNightscout();
-            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
-            // TODO - throw, don't return
-            return;
-        }
+            // avoid polling when too close to sensor-pump comms
+            if (((timePollExpected - timePollStarted) > 5000L) && ((timePollExpected - timePollStarted) < (POLL_GRACE_PERIOD_MS + 45000L))) {
+                sendStatus("Please wait: Poll due in " + ((timePollExpected - timePollStarted) / 1000L) + " seconds");
+                MedtronicCnlAlarmManager.setAlarm(timePollExpected);
+                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);
+            final short pumpBatteryLevel = dataStore.getLastPumpStatus().getBatteryPercentage();
+            long pollInterval = configurationStore.getPollInterval();
+            if ((pumpBatteryLevel > 0) && (pumpBatteryLevel <= 25)) {
+                pollInterval = configurationStore.getLowBatteryPollInterval();
+            }
 
-        try {
-            mHidDevice.open();
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to open serial device", e);
-            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
             // TODO - throw, don't return
-            return;
-        }
+            if (!openUsbDevice())
+                return;
 
-        DateFormat df = new SimpleDateFormat("HH:mm:ss", Locale.US);
+            MedtronicCnlReader cnlReader = new MedtronicCnlReader(mHidDevice);
 
-        MedtronicCnlReader cnlReader = new MedtronicCnlReader(mHidDevice);
+            Realm realm = Realm.getDefaultInstance();
+            realm.beginTransaction();
 
-        Realm realm = Realm.getDefaultInstance();
-        realm.beginTransaction();
+            try {
+                sendStatus("Connecting to Contour Next Link");
+                Log.d(TAG, "Connecting to Contour Next Link");
+                cnlReader.requestDeviceInfo();
+
+                // Is the device already configured?
+                ContourNextLinkInfo info = realm
+                        .where(ContourNextLinkInfo.class)
+                        .equalTo("serialNumber", cnlReader.getStickSerial())
+                        .findFirst();
 
-        try {
-            sendStatus("Connecting to Contour Next Link");
-            Log.d(TAG, "Connecting to Contour Next Link");
-            cnlReader.requestDeviceInfo();
-
-            // Is the device already configured?
-            ContourNextLinkInfo info = realm
-                    .where(ContourNextLinkInfo.class)
-                    .equalTo("serialNumber", cnlReader.getStickSerial())
-                    .findFirst();
-
-            if (info == null) {
-                info = realm.createObject(ContourNextLinkInfo.class, cnlReader.getStickSerial());
-            }
+                if (info == null) {
+                    info = realm.createObject(ContourNextLinkInfo.class, cnlReader.getStickSerial());
+                }
 
-            cnlReader.getPumpSession().setStickSerial(info.getSerialNumber());
+                cnlReader.getPumpSession().setStickSerial(info.getSerialNumber());
 
-            cnlReader.enterControlMode();
+                cnlReader.enterControlMode();
 
-            try {
-                cnlReader.enterPassthroughMode();
-                cnlReader.openConnection();
+                try {
+                    cnlReader.enterPassthroughMode();
+                    cnlReader.openConnection();
 
-                cnlReader.requestReadInfo();
+                    cnlReader.requestReadInfo();
 
-                String key = info.getKey();
+                    String key = info.getKey();
 
-                if (key == null) {
-                    cnlReader.requestLinkKey();
+                    if (key == null) {
+                        cnlReader.requestLinkKey();
 
-                    info.setKey(MessageUtils.byteArrayToHexString(cnlReader.getPumpSession().getKey()));
-                    key = info.getKey();
-                }
+                        info.setKey(MessageUtils.byteArrayToHexString(cnlReader.getPumpSession().getKey()));
+                        key = info.getKey();
+                    }
 
-                cnlReader.getPumpSession().setKey(MessageUtils.hexStringToByteArray(key));
+                    cnlReader.getPumpSession().setKey(MessageUtils.hexStringToByteArray(key));
 
-                long pumpMAC = cnlReader.getPumpSession().getPumpMAC();
-                Log.i(TAG, "PumpInfo MAC: " + (pumpMAC & 0xffffff));
-                PumpInfo activePump = realm
-                        .where(PumpInfo.class)
-                        .equalTo("pumpMac", pumpMAC)
-                        .findFirst();
+                    long pumpMAC = cnlReader.getPumpSession().getPumpMAC();
+                    Log.i(TAG, "PumpInfo MAC: " + (pumpMAC & 0xffffff));
+                    PumpInfo activePump = realm
+                            .where(PumpInfo.class)
+                            .equalTo("pumpMac", pumpMAC)
+                            .findFirst();
 
-                if (activePump == null) {
-                    activePump = realm.createObject(PumpInfo.class, pumpMAC);
-                }
+                    if (activePump == null) {
+                        activePump = realm.createObject(PumpInfo.class, pumpMAC);
+                    }
 
-                activePump.updateLastQueryTS();
+                    activePump.updateLastQueryTS();
 
-                byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel());
-                if (radioChannel == 0) {
-                    sendStatus("Could not communicate with the pump. Is it nearby?");
-                    Log.i(TAG, "Could not communicate with the pump. Is it nearby?");
-                    pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available
-                } else {
-                    dataStore.setActivePumpMac(pumpMAC);
+                    byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel());
+                    if (radioChannel == 0) {
+                        sendStatus("Could not communicate with the pump. Is it nearby?");
+                        Log.i(TAG, "Could not communicate with the pump. Is it nearby?");
+                        pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available
+                    } else {
+                        dataStore.setActivePumpMac(pumpMAC);
 
-                    activePump.setLastRadioChannel(radioChannel);
-                    sendStatus(String.format(Locale.getDefault(), "Connected on channel %d  RSSI: %d%%", (int) radioChannel, cnlReader.getPumpSession().getRadioRSSIpercentage()));
-                    Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel));
+                        activePump.setLastRadioChannel(radioChannel);
+                        sendStatus(String.format(Locale.getDefault(), "Connected on channel %d  RSSI: %d%%", (int) radioChannel, cnlReader.getPumpSession().getRadioRSSIpercentage()));
+                        Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel));
 
-                    // read pump status
-                    PumpStatusEvent pumpRecord = realm.createObject(PumpStatusEvent.class);
+                        // read pump status
+                        PumpStatusEvent pumpRecord = realm.createObject(PumpStatusEvent.class);
 
-                    String deviceName = String.format("medtronic-600://%s", cnlReader.getStickSerial());
-                    activePump.setDeviceName(deviceName);
+                        String deviceName = String.format("medtronic-600://%s", cnlReader.getStickSerial());
+                        activePump.setDeviceName(deviceName);
 
-                    // TODO - this should not be necessary. We should reverse lookup the device name from PumpInfo
-                    pumpRecord.setDeviceName(deviceName);
+                        // TODO - this should not be necessary. We should reverse lookup the device name from PumpInfo
+                        pumpRecord.setDeviceName(deviceName);
 
-                    long pumpTime = cnlReader.getPumpTime().getTime();
-                    long pumpOffset = pumpTime - System.currentTimeMillis();
-                    Log.d(TAG, "Time offset between pump and device: " + pumpOffset + " millis.");
+                        long pumpTime = cnlReader.getPumpTime().getTime();
+                        long pumpOffset = pumpTime - System.currentTimeMillis();
+                        Log.d(TAG, "Time offset between pump and device: " + pumpOffset + " millis.");
 
-                    // TODO - send ACTION to MainActivity to show offset between pump and uploader.
-                    pumpRecord.setPumpTimeOffset(pumpOffset);
-                    pumpRecord.setPumpDate(new Date(pumpTime - pumpOffset));
-                    cnlReader.updatePumpStatus(pumpRecord);
+                        // TODO - send ACTION to MainActivity to show offset between pump and uploader.
+                        pumpRecord.setPumpTimeOffset(pumpOffset);
+                        pumpRecord.setPumpDate(new Date(pumpTime - pumpOffset));
+                        cnlReader.updatePumpStatus(pumpRecord);
 
                     if (pumpRecord.getSgv() != 0) {
                         String offsetSign = "";
                         if (pumpOffset > 0) {
                             offsetSign = "+";
                         }
-                        sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv()) + "  At: " + df.format(pumpRecord.getEventDate().getTime()) + "  Pump: " + offsetSign + (pumpOffset / 1000L) + "sec");  //note: event time is currently stored with offset
+                        sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv()) + "  At: " + dateFormatter.format(pumpRecord.getSgvDate().getTime()) + "  Pump: " + offsetSign + (pumpOffset / 1000L) + "sec");  //note: event time is currently stored with offset
 
                         // Check if pump sent old event when new expected
                         if (pumpRecord != null &&
@@ -267,15 +246,12 @@ public class MedtronicCnlIntentService extends IntentService {
                             sendStatus("Pump sent old SGV event, re-polling...");
                         }
 
-                        //MainActivity.timeLastGoodSGV =  pumpRecord.getEventDate().getTime(); // track last good sgv event time
-                        //MainActivity.pumpBattery =  pumpRecord.getBatteryPercentage(); // track pump battery
-                        timeLastGoodSGV = pumpRecord.getEventDate().getTime();
                         dataStore.clearUnavailableSGVCount(); // reset unavailable sgv count
 
                         // Check that the record doesn't already exist before committing
                         RealmResults<PumpStatusEvent> checkExistingRecords = activePump.getPumpHistory()
                                 .where()
-                                .equalTo("eventDate", pumpRecord.getEventDate())    // >>>>>>> check as event date may not = exact pump event date due to it being stored with offset added this could lead to dup events due to slight variability in time offset
+                                .equalTo("sgvDate", pumpRecord.getSgvDate())
                                 .equalTo("sgv", pumpRecord.getSgv())
                                 .findAll();
 
@@ -290,83 +266,120 @@ public class MedtronicCnlIntentService extends IntentService {
                         dataStore.incUnavailableSGVCount(); // poll clash detection
                     }
 
-                    realm.commitTransaction();
-                    // Tell the Main Activity we have new data
-                    sendMessage(Constants.ACTION_UPDATE_PUMP);
-                }
+                        realm.commitTransaction();
+                        // Tell the Main Activity we have new data
+                        sendMessage(Constants.ACTION_UPDATE_PUMP);
+                    }
 
-            } catch (UnexpectedMessageException e) {
-                Log.e(TAG, "Unexpected Message", e);
-                sendStatus("Communication Error: " + e.getMessage());
-                pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L);
+                } catch (UnexpectedMessageException e) {
+                    Log.e(TAG, "Unexpected Message", e);
+                    sendStatus("Communication Error: " + e.getMessage());
+                    pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L);
+                } catch (TimeoutException e) {
+                    Log.e(TAG, "Timeout communicating with the Contour Next Link.", e);
+                    sendStatus("Timeout communicating with the Contour Next Link.");
+                    pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L);
+                } catch (NoSuchAlgorithmException e) {
+                    Log.e(TAG, "Could not determine CNL HMAC", e);
+                    sendStatus("Error connecting to Contour Next Link: Hashing error.");
+                } finally {
+                    try {
+                        cnlReader.closeConnection();
+                        cnlReader.endPassthroughMode();
+                        cnlReader.endControlMode();
+                    } catch (NoSuchAlgorithmException e) {
+                    }
+
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "Error connecting to Contour Next Link.", e);
+                sendStatus("Error connecting to Contour Next Link.");
+            } catch (ChecksumException e) {
+                Log.e(TAG, "Checksum error getting message from the Contour Next Link.", e);
+                sendStatus("Checksum error getting message from the Contour Next Link.");
+            } catch (EncryptionException e) {
+                Log.e(TAG, "Error decrypting messages from Contour Next Link.", e);
+                sendStatus("Error decrypting messages from Contour Next Link.");
             } catch (TimeoutException e) {
                 Log.e(TAG, "Timeout communicating with the Contour Next Link.", e);
                 sendStatus("Timeout communicating with the Contour Next Link.");
-                pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L);
-            } catch (NoSuchAlgorithmException e) {
-                Log.e(TAG, "Could not determine CNL HMAC", e);
-                sendStatus("Error connecting to Contour Next Link: Hashing error.");
+            } catch (UnexpectedMessageException e) {
+                Log.e(TAG, "Could not close connection.", e);
+                sendStatus("Could not close connection: " + e.getMessage());
             } finally {
-                try {
-                    cnlReader.closeConnection();
-                    cnlReader.endPassthroughMode();
-                    cnlReader.endControlMode();
-                } catch (NoSuchAlgorithmException e) {
+                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();
                 }
 
+                uploadPollResults();
+                scheduleNextPoll(timePollStarted, timeLastGoodSGV, pollInterval);
             }
-        } catch (IOException e) {
-            Log.e(TAG, "Error connecting to Contour Next Link.", e);
-            sendStatus("Error connecting to Contour Next Link.");
-        } catch (ChecksumException e) {
-            Log.e(TAG, "Checksum error getting message from the Contour Next Link.", e);
-            sendStatus("Checksum error getting message from the Contour Next Link.");
-        } catch (EncryptionException e) {
-            Log.e(TAG, "Error decrypting messages from Contour Next Link.", e);
-            sendStatus("Error decrypting messages from Contour Next Link.");
-        } catch (TimeoutException e) {
-            Log.e(TAG, "Timeout communicating with the Contour Next Link.", e);
-            sendStatus("Timeout communicating with the Contour Next Link.");
-        } catch (UnexpectedMessageException e) {
-            Log.e(TAG, "Could not close connection.", e);
-            sendStatus("Could not close connection: " + e.getMessage());
         } finally {
-            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();
-            }
-            // TODO - set status if offline or Nightscout not reachable
-            sendToXDrip();
-            uploadToNightscout();
-
-            // smart polling and pump-sensor poll clash detection
-            long lastActualPollTime = timePollStarted;
-            if (timeLastGoodSGV > 0) {
-                lastActualPollTime = timeLastGoodSGV + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((System.currentTimeMillis() - (timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
-            }
-            long nextActualPollTime = lastActualPollTime + POLL_PERIOD_MS;
-            long nextRequestedPollTime = lastActualPollTime + pollInterval;
-            if ((nextRequestedPollTime - System.currentTimeMillis()) < 10000L) {
-                nextRequestedPollTime = nextActualPollTime;
-            }
-            // extended unavailable SGV may be due to clash with the current polling time
-            // while we wait for a good SGV event, polling is auto adjusted by offsetting the next poll based on miss count
-            if (dataStore.getUnavailableSGVCount() > 0) {
-                if (timeLastGoodSGV == 0) {
-                    nextRequestedPollTime += POLL_PERIOD_MS / 5L; // if there is a uploader/sensor poll clash on startup then this will push the next attempt out by 60 seconds
-                } else if (dataStore.getUnavailableSGVCount() > 2) {
-                    sendStatus("Warning: No SGV available from pump for " + dataStore.getUnavailableSGVCount() + " attempts");
-                    nextRequestedPollTime += ((long) ((dataStore.getUnavailableSGVCount() - 2) % 5)) * (POLL_PERIOD_MS / 10L); // adjust poll time in 1/10 steps to avoid potential poll clash (max adjustment at 5/10)
-                }
+            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+        }
+    }
+
+    private void scheduleNextPoll(long timePollStarted, long timeLastGoodSGV, long pollInterval) {
+        // smart polling and pump-sensor poll clash detection
+        long lastActualPollTime = timePollStarted;
+        if (timeLastGoodSGV > 0) {
+            lastActualPollTime = timeLastGoodSGV + POLL_GRACE_PERIOD_MS + (POLL_PERIOD_MS * ((System.currentTimeMillis() - (timeLastGoodSGV + POLL_GRACE_PERIOD_MS)) / POLL_PERIOD_MS));
+        }
+        long nextActualPollTime = lastActualPollTime + POLL_PERIOD_MS;
+        long nextRequestedPollTime = lastActualPollTime + pollInterval;
+        if ((nextRequestedPollTime - System.currentTimeMillis()) < 10000L) {
+            nextRequestedPollTime = nextActualPollTime;
+        }
+        // extended unavailable SGV may be due to clash with the current polling time
+        // while we wait for a good SGV event, polling is auto adjusted by offsetting the next poll based on miss count
+        if (dataStore.getUnavailableSGVCount() > 0) {
+            if (timeLastGoodSGV == 0) {
+                nextRequestedPollTime += POLL_PERIOD_MS / 5L; // if there is a uploader/sensor poll clash on startup then this will push the next attempt out by 60 seconds
+            } else if (dataStore.getUnavailableSGVCount() > 2) {
+                sendStatus("Warning: No SGV available from pump for " + dataStore.getUnavailableSGVCount() + " attempts");
+                nextRequestedPollTime += ((long) ((dataStore.getUnavailableSGVCount() - 2) % 5)) * (POLL_PERIOD_MS / 10L); // adjust poll time in 1/10 steps to avoid potential poll clash (max adjustment at 5/10)
             }
-            MedtronicCnlAlarmManager.setAlarm(nextRequestedPollTime);
-            sendStatus("Next poll due at: " + df.format(nextRequestedPollTime));
+        }
+        MedtronicCnlAlarmManager.setAlarm(nextRequestedPollTime);
+        sendStatus("Next poll due at: " + dateFormatter.format(nextRequestedPollTime));
+    }
 
-            MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
+    /**
+     * @return if device acquisition was successful
+     */
+    private boolean openUsbDevice() {
+        if (!hasUsbHostFeature()) {
+            sendStatus("It appears that this device doesn't support USB OTG.");
+            Log.e(TAG, "Device does not support USB OTG");
+            return false;
         }
+
+        UsbDevice cnlStick = UsbHidDriver.getUsbDevice(mUsbManager, USB_VID, USB_PID);
+        if (cnlStick == null) {
+            sendStatus("USB connection error. Is the Contour Next Link plugged in?");
+            Log.w(TAG, "USB connection error. Is the CNL plugged in?");
+            return false;
+        }
+
+        if (!mUsbManager.hasPermission(UsbHidDriver.getUsbDevice(mUsbManager, USB_VID, USB_PID))) {
+            sendMessage(Constants.ACTION_NO_USB_PERMISSION);
+            return false;
+        }
+        mHidDevice = UsbHidDriver.acquire(mUsbManager, cnlStick);
+
+        try {
+            mHidDevice.open();
+        } catch (Exception e) {
+            sendStatus("Unable to open USB device");
+            Log.e(TAG, "Unable to open serial device", e);
+            return false;
+        }
+
+        return true;
     }
 
     // reliable wake alarm manager wake up for all android versions
@@ -380,6 +393,11 @@ public class MedtronicCnlIntentService extends IntentService {
             alarm.set(AlarmManager.RTC_WAKEUP, wakeTime, pendingIntent);
     }
 
+    private void uploadPollResults() {
+        sendToXDrip();
+        uploadToNightscout();
+    }
+
     private void sendToXDrip() {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
         if (prefs.getBoolean(getString(R.string.preference_enable_xdrip_plus), false)) {
@@ -392,6 +410,7 @@ public class MedtronicCnlIntentService extends IntentService {
     }
 
     private void uploadToNightscout() {
+        // TODO - set status if offline or Nightscout not reachable
         Intent receiverIntent = new Intent(this, NightscoutUploadReceiver.class);
         final long timestamp = System.currentTimeMillis() + 1000L;
         final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, (int) timestamp, receiverIntent, PendingIntent.FLAG_ONE_SHOT);
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java b/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
index ce79ab7900ef741ecb3c8f35550eebd019f34d69..1f40ab015abd146de2c596efb414ad798df58594 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
@@ -71,6 +71,8 @@ public class EntriesSerializer implements JsonSerializer<PumpStatusEvent> {
         }
     }
 
+    // TODO currentnly unused, see info.nightscout.android.xdrip_plus.XDripPlusUploadIntentService.addSgvEntry()
+    // TODO also, proper method name
     @Override
     public JsonElement serialize(PumpStatusEvent src, Type typeOfSrc, JsonSerializationContext context) {
         final JsonObject jsonObject = new JsonObject();
@@ -78,8 +80,8 @@ public class EntriesSerializer implements JsonSerializer<PumpStatusEvent> {
         jsonObject.addProperty("direction", getDirectionString(src.getCgmTrend()));
         jsonObject.addProperty("device", src.getDeviceName());
         jsonObject.addProperty("type", "sgv");
-        jsonObject.addProperty("date", src.getEventDate().getTime());
-        jsonObject.addProperty("dateString", String.valueOf(src.getEventDate()));
+        jsonObject.addProperty("date", src.getSgvDate().getTime());
+        jsonObject.addProperty("dateString", String.valueOf(src.getSgvDate()));
 
         return jsonObject;
     }
diff --git a/app/src/main/java/info/nightscout/android/utils/DataStore.java b/app/src/main/java/info/nightscout/android/utils/DataStore.java
index fbd2a02011f40323c64f1b6cf977c59869555a3b..39fe120d971acda594d91203e040fd2125c2a3de 100644
--- a/app/src/main/java/info/nightscout/android/utils/DataStore.java
+++ b/app/src/main/java/info/nightscout/android/utils/DataStore.java
@@ -26,6 +26,7 @@ public class DataStore {
 
             // set some initial dummy values
             PumpStatusEvent dummyStatus = new PumpStatusEvent();
+            dummyStatus.setSgvDate(new Date());
 
             // bypass setter to avoid dealing with a real Realm object
             instance.lastPumpStatus = dummyStatus;
diff --git a/app/src/main/java/info/nightscout/android/xdrip_plus/XDripPlusUploadIntentService.java b/app/src/main/java/info/nightscout/android/xdrip_plus/XDripPlusUploadIntentService.java
index 20a1183a83ecbae9432f0c048d5088a29f9ba8d5..e06a88b8cf047dde4d5a812b58198e69bd508573 100644
--- a/app/src/main/java/info/nightscout/android/xdrip_plus/XDripPlusUploadIntentService.java
+++ b/app/src/main/java/info/nightscout/android/xdrip_plus/XDripPlusUploadIntentService.java
@@ -145,8 +145,8 @@ public class XDripPlusUploadIntentService extends IntentService {
         json.put("direction", EntriesSerializer.getDirectionString(pumpRecord.getCgmTrend()));
         json.put("device", pumpRecord.getDeviceName());
         json.put("type", "sgv");
-        json.put("date", pumpRecord.getEventDate().getTime());
-        json.put("dateString", pumpRecord.getEventDate());
+        json.put("date", pumpRecord.getSgvDate().getTime());
+        json.put("dateString", pumpRecord.getSgvDate());
 
         entriesArray.put(json);
     }