diff --git a/app/build.gradle b/app/build.gradle
index 0da5ebe89c0ea187f6d9e671f22c4c977a59dd8e..68e1d9d74a77133b4e43f5bbafc086de825f1067 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -156,7 +156,7 @@ dependencies {
     compile 'com.mikepenz:google-material-typeface:2.2.0.1.original@aar'
     compile 'uk.co.chrisjenx:calligraphy:2.2.0'
     compile 'com.bugfender.sdk:android:0.7.2'
-    compile 'com.jjoe64:graphview:4.2.1'
+    compile 'com.jjoe64:graphview:4.0.1'
     compile 'com.google.code.gson:gson:2.7'
     compile 'com.squareup.retrofit2:retrofit:2.1.0'
     compile 'com.squareup.retrofit2:converter-gson:2.1.0'
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 a87d92401e7c4dc1bff7521505dfe7db35c74381..3083b742e3c7b6203339943ebf41815cf6357f04 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
@@ -322,6 +322,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         mChart.getViewport().setMaxX(now);
         mChart.getViewport().setMinX(left);
 
+// due to bug in GraphView v4.2.1 using setNumHorizontalLabels reverted to using v4.0.1 and setOnXAxisBoundsChangedListener is n/a in this version
+/*
         mChart.getViewport().setOnXAxisBoundsChangedListener(new Viewport.OnXAxisBoundsChangedListener() {
             @Override
             public void onXAxisBoundsChanged(double minX, double maxX, Reason reason) {
@@ -329,7 +331,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                 hasZoomedChart = (rightX != maxX || rightX - chartZoom * 60 * 60 * 1000 != minX);
             }
         });
-
+*/
         mChart.setOnLongClickListener(new View.OnLongClickListener() {
             @Override
             public boolean onLongClick(View v) {
@@ -343,7 +345,9 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
             }
         });
         mChart.getGridLabelRenderer().setNumHorizontalLabels(6);
-        mChart.getGridLabelRenderer().setHumanRounding(false);
+
+// due to bug in GraphView v4.2.1 using setNumHorizontalLabels reverted to using v4.0.1 and setHumanRounding is n/a in this version
+//        mChart.getGridLabelRenderer().setHumanRounding(false);
 
         mChart.getGridLabelRenderer().setLabelFormatter(
                 new DefaultLabelFormatter() {
@@ -463,14 +467,15 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     }
 
     private void startCgmServiceDelayed(long delay) {
-        RealmResults<PumpStatusEvent> results = mRealm.where(PumpStatusEvent.class)
-                .findAllSorted("sgvDate", Sort.DESCENDING);
-
-        if (results.size() > 0) {
-            startCgmService(getNextPoll(results.first()) + delay);
-        } else {
-            startCgmService(System.currentTimeMillis() + (delay == 0 ? 1000 : delay));
+        if (!mRealm.isClosed()) {
+            RealmResults<PumpStatusEvent> results = mRealm.where(PumpStatusEvent.class)
+                    .findAllSorted("eventDate", Sort.DESCENDING);
+            if (results.size() > 0) {
+                startCgmService(getNextPoll(results.first()) + delay);
+                return;
+            }
         }
+        startCgmService(System.currentTimeMillis() + (delay == 0 ? 1000 : delay));
     }
 
     private void startCgmService(long initialPoll) {
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 539e28d298f8aaf801e4bc997ee180c0508719b9..69106aa982bcf1bb08895ca3db121cc70597893d 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlReader.java
@@ -172,18 +172,6 @@ public class MedtronicCnlReader {
     public Date getPumpTime() throws EncryptionException, IOException, ChecksumException, TimeoutException, UnexpectedMessageException {
         Log.d(TAG, "Begin getPumpTime");
 
-        // CNL<-->PUMP comms can have occasional short lived noise causing errors, retrying once catches this
-        try {
-            PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice);
-            // ignore the first error. Just log retry
-            // Log.d(TAG, "Finished getPumpTime with date " + response.getPumpTime());
-            return response.getPumpTime();
-        } catch (UnexpectedMessageException e) {
-            Log.e(TAG, "Unexpected Message", e);
-        } catch (TimeoutException e) {
-            Log.e(TAG, "Timeout communicating with the Contour Next Link.", e);
-        }
-
         PumpTimeResponseMessage response = new PumpTimeRequestMessage(mPumpSession).send(mDevice);
 
         Log.d(TAG, "Finished getPumpTime with date " + response.getPumpTime());
@@ -193,23 +181,10 @@ public class MedtronicCnlReader {
     public PumpStatusEvent updatePumpStatus(PumpStatusEvent pumpRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException, UnexpectedMessageException {
         Log.d(TAG, "Begin updatePumpStatus");
 
-        // CNL<-->PUMP comms can have occasional short lived noise causing errors, retrying once catches this
-        try {
-            PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice);
-            response.updatePumpRecord(pumpRecord);
-            Log.d(TAG, "Finished updatePumpStatus: " + pumpRecord.toString());
-            return pumpRecord;
-        } catch (UnexpectedMessageException e) {
-            Log.e(TAG, "Unexpected Message", e);
-        } catch (TimeoutException e) {
-            Log.e(TAG, "Timeout communicating with the Contour Next Link.", e);
-        }
-
         PumpStatusResponseMessage response = new PumpStatusRequestMessage(mPumpSession).send(mDevice);
         response.updatePumpRecord(pumpRecord);
 
-        Log.d(TAG, "Finished updatePumpStatus: " + pumpRecord.toString());
-
+        Log.d(TAG, "Finished updatePumpStatus");
         return pumpRecord;
     }
 
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java
index 912279370a9be2cddcb3cc4103b9527bc742c42f..bc8aa8a6a5f1850c3c25b6dd128d80d29d1b19a6 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java
@@ -5,6 +5,7 @@ import java.io.IOException;
 import info.nightscout.android.medtronic.MedtronicCnlSession;
 import info.nightscout.android.medtronic.exception.ChecksumException;
 import info.nightscout.android.medtronic.exception.EncryptionException;
+import info.nightscout.android.medtronic.exception.UnexpectedMessageException;
 
 /**
  * Created by volker on 10.12.2016.
@@ -15,6 +16,24 @@ public class CloseConnectionRequestMessage extends ContourNextLinkBinaryRequestM
         super(CommandType.CLOSE_CONNECTION, pumpSession, payload);
     }
 
+    @Override
+    public CloseConnectionResponseMessage send(UsbHidDriver mDevice, int millis) throws IOException, TimeoutException, ChecksumException, EncryptionException, UnexpectedMessageException {
+
+        // clear unexpected incoming messages
+        clearMessage(mDevice);
+
+        sendMessage(mDevice);
+        if (millis > 0) {
+            try {
+                Thread.sleep(millis);
+            } catch (InterruptedException e) {
+            }
+        }
+
+        CloseConnectionResponseMessage response = this.getResponse(readMessage(mDevice));
+        return response;
+    }
+
     @Override
     protected CloseConnectionResponseMessage getResponse(byte[] payload) throws ChecksumException, EncryptionException, IOException {
         return new CloseConnectionResponseMessage(payload);
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java
index 163f42775f2161bcf92ae7e743c2a0435ba99165..13858f38e76f4e761bd2bd13e6a343683ab34daf 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusRequestMessage.java
@@ -40,11 +40,13 @@ public class PumpStatusRequestMessage extends MedtronicSendMessageRequestMessage
             } catch (InterruptedException e) {
             }
         }
-        PumpStatusResponseMessage response = this.getResponse(readMessage(mDevice));
+        // Read the 0x80
+        byte[] payload = readMessage(mDevice);
 
         // clear unexpected incoming messages
         clearMessage(mDevice);
 
+        PumpStatusResponseMessage response = this.getResponse(payload);
         return response;
     }
 
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java
index 592800406888cb5c6ce3860642c785b274ce79a2..c4063b53e0681c472885b90ebf4ee6d7aa9ce231 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpTimeRequestMessage.java
@@ -36,11 +36,12 @@ public class PumpTimeRequestMessage extends MedtronicSendMessageRequestMessage<P
             }
         }
         // Read the 0x80
-        PumpTimeResponseMessage response = this.getResponse(readMessage(mDevice));
+        byte[] payload = readMessage(mDevice);
 
         // Pump sends additional 0x80 message when not using EHSM, lets clear this and any unexpected incoming messages
         clearMessage(mDevice);
 
+        PumpTimeResponseMessage response = this.getResponse(payload);
         return response;
     }
 
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 03e2653028c223b5fae44d08594345b7be185b07..9b46b76a7c1261f278ce403d497c7495e08c24da 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
@@ -251,27 +251,40 @@ public class MedtronicCnlIntentService extends IntentService {
                     pumpRecord.setPumpDate(new Date(pumpTime - pumpOffset));
                     cnlReader.updatePumpStatus(pumpRecord);
 
-                    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
-
-                    // Check if pump sent old event when new expected and schedule a re-poll
-                    if (pumpRecord != null &&
-                            dataStore.getLastPumpStatus() != null &&
-                            dataStore.getLastPumpStatus().getPumpDate() != null &&
-                            ((pumpRecord.getPumpDate().getTime() - dataStore.getLastPumpStatus().getPumpDate().getTime()) < 5000L) &&
-                            ((timePollExpected - timePollStarted) < 5000L)) {
-                        pollInterval = 90000L; // polling interval set to 90 seconds
-                        sendStatus("Pump sent old SGV event, re-polling...");
-                    }
-
-                    activePump.getPumpHistory().add(pumpRecord);
-                    dataStore.setLastPumpStatus(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
+
+                        // Check if pump sent old event when new expected
+                        if (pumpRecord != null &&
+                                dataStore.getLastPumpStatus() != null &&
+                                dataStore.getLastPumpStatus().getPumpDate() != null &&
+                                ((pumpRecord.getPumpDate().getTime() - dataStore.getLastPumpStatus().getPumpDate().getTime()) < 5000L) &&
+                                ((timePollExpected - timePollStarted) < 5000L)) {
+                            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("sgv", pumpRecord.getSgv())
+                                .findAll();
+
+                        // There should be the 1 record we've already added in this transaction.
+                        if (checkExistingRecords.size() == 0) {
+                            activePump.getPumpHistory().add(pumpRecord);
+                            dataStore.setLastPumpStatus(pumpRecord);
+                        }
+
                     } else {
                         sendStatus("SGV: unavailable from pump");
                         dataStore.incUnavailableSGVCount(); // poll clash detection