diff --git a/app/build.gradle b/app/build.gradle
index 13710f83b2adda6231962da4fd5883ef4fe80932..a8b8c6dadedc0cf41970a355f31ff8b7a0592d5f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -51,8 +51,15 @@ def getBugfenderApiKey() {
     String bugfenderApiKey = System.getenv("BUGFENDER_API_KEY")
 
     if(bugfenderApiKey == null) {
-        logger.warn("Bugfender API key not set")
-        bugfenderApiKey = ""
+        File file = new File("app/bugfender.properties")
+        if (file.exists()) {
+            Properties properties = new Properties()
+            properties.load(new FileInputStream(file.getAbsolutePath().toString()))
+            bugfenderApiKey = properties.getProperty("apiKey", "")
+        } else {
+            logger.warn("Bugfender API key not set")
+            bugfenderApiKey = ""
+        }
     }
 
     return "\"" + bugfenderApiKey + "\""
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 f8f625ecdd33c35a36cdb1499af05e32011e1c9a..e458cdbb43aab20544dd8ef25a17bdf4cc3f5c47 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
@@ -109,6 +109,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     private Realm mRealm;
     private Realm storeRealm;
     private StatusMessageReceiver statusMessageReceiver = new StatusMessageReceiver();
+    private UpdatePumpReceiver updatePumpReceiver = new UpdatePumpReceiver();
     private UsbReceiver usbReceiver = new UsbReceiver();
     private BatteryReceiver batteryReceiver = new BatteryReceiver();
 
@@ -183,7 +184,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                 statusMessageReceiver,
                 new IntentFilter(MedtronicCnlIntentService.Constants.ACTION_STATUS_MESSAGE));
         LocalBroadcastManager.getInstance(this).registerReceiver(
-                new UpdatePumpReceiver(),
+                updatePumpReceiver,
                 new IntentFilter(MedtronicCnlIntentService.Constants.ACTION_UPDATE_PUMP));
 
         mEnableCgmService = Eula.show(this, prefs);
@@ -207,7 +208,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                 new IntentFilter(MedtronicCnlIntentService.Constants.ACTION_USB_REGISTER));
 
         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
-
         if (toolbar != null) {
             setSupportActionBar(toolbar);
             getSupportActionBar().setDisplayHomeAsUpEnabled(false);
@@ -590,11 +590,15 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
         super.onDestroy();
 
+        cancelDisplayRefreshLoop();
+
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(statusMessageReceiver);
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(updatePumpReceiver);
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(usbReceiver);
         unregisterReceiver(usbReceiver);
         unregisterReceiver(batteryReceiver);
 
         PreferenceManager.getDefaultSharedPreferences(getBaseContext()).unregisterOnSharedPreferenceChangeListener(this);
-        cancelDisplayRefreshLoop();
 
         if (!storeRealm.isClosed()) {
             storeRealm.close();
diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java
index 034d3914ca1093cbc75d4818afb0da21fcdd3b42..39f5e1413ed2d29f0a887a1c10d3dc7ca4cc4506 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpStatusResponseMessage.java
@@ -156,6 +156,7 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa
 
         // Predictive low suspend
         // TODO - there is more status info in this byte other than just a boolean yes/no
+        // noted: 0x01=high 0x04=before high 0x08=before low 0x0A=low 0x80=suspend 0x92=suspend low
         lowSuspendActive = statusBuffer.get(0x3F) != 0;
 
         // Recent Bolus Wizard
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 0d0a80bd0594683632b323b0184f8f996f0e0218..d1a80edadf8b029d8aedefa861d07879285c2c9a 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
@@ -46,34 +46,43 @@ public class MedtronicCnlIntentService extends IntentService {
     public final static int USB_VID = 0x1a79;
     public final static int USB_PID = 0x6210;
     public final static long USB_WARMUP_TIME_MS = 5000L;
+
     public final static long POLL_PERIOD_MS = 300000L;
     public final static long LOW_BATTERY_POLL_PERIOD_MS = 900000L;
     // Number of additional seconds to wait after the next expected CGM poll, so that we don't interfere with CGM radio comms.
     public final static long POLL_GRACE_PERIOD_MS = 30000L;
+    // Number of seconds before the next expected CGM poll that we will allow uploader comms to start
     public final static long POLL_PRE_GRACE_PERIOD_MS = 45000L;
-
-    public static final String ICON_WARN = "{ion-alert-circled} ";
-    public static final String ICON_BGL = "{ion-waterdrop} ";
-    public static final String ICON_USB = "{ion-usb} ";
-    public static final String ICON_INFO = "{ion-information_circled} ";
-    public static final String ICON_HELP = "{ion-ios-lightbulb} ";
-    public static final String ICON_SETTING = "{ion-android-settings} ";
-    public static final String ICON_HEART = "{ion-heart} ";
-    public static final String ICON_LOW = "{ion-battery_low} ";
-    public static final String ICON_FULL = "{ion-battery_full} ";
-    public static final String ICON_RESV = "{ion-paintbucket} ";
-    public static final String ICON_CGM = "{ion-ios-pulse_strong} ";
-    public static final String ICON_MEDICAL = "{ion-ios-medical} ";
-    public static final String ICON_BOLUS = "{ion-erlenmeyer-flask} ";
-    public static final String ICON_BASAL = "{ion-ios-timer} ";
-    public static final String ICON_NOTE = "{ion_android_notifications} ";
+    // cgm n/a events to trigger anti clash poll timing
+    public final static int POLL_ANTI_CLASH = 3;
+
+    // TODO - use a message type and insert icon as part of ui status message handling
+    public static final String ICON_WARN = "{ion_alert_circled} ";
+    public static final String ICON_BGL = "{ion_waterdrop} ";
+    public static final String ICON_USB = "{ion_usb} ";
+    public static final String ICON_INFO = "{ion_information_circled} ";
+    public static final String ICON_HELP = "{ion_ios_lightbulb} ";
+    public static final String ICON_SETTING = "{ion_android_settings} ";
+    public static final String ICON_HEART = "{ion_heart} ";
+    public static final String ICON_LOW = "{ion_battery_low} ";
+    public static final String ICON_FULL = "{ion_battery_full} ";
+    public static final String ICON_CGM = "{ion_ios_pulse_strong} ";
+    public static final String ICON_SUSPEND = "{ion_pause} ";
+    public static final String ICON_RESUME = "{ion_play} ";
+    public static final String ICON_BOLUS = "{ion_skip_forward} ";
+    public static final String ICON_BASAL = "{ion_skip_forward} ";
+    public static final String ICON_CHANGE = "{ion_android_hand} ";
+    public static final String ICON_BELL = "{ion_android_notifications} ";
+    public static final String ICON_NOTE = "{ion_clipboard} ";
 
     // show warning message after repeated errors
     private final static int ERROR_COMMS_AT = 4;
-    private final static int ERROR_CONNECT_AT = 8;
-    private final static int ERROR_SIGNAL_AT = 8;
-    private final static int ERROR_PUMPLOSTSENSOR_AT = 8;
+    private final static int ERROR_CONNECT_AT = 6;
+    private final static int ERROR_SIGNAL_AT = 6;
+    private final static int ERROR_PUMPLOSTSENSOR_AT = 6;
+    private final static int ERROR_PUMPBATTERY_AT = 3;
     private final static int ERROR_PUMPCLOCK_AT = 8;
+    private final static int ERROR_PUMPCLOCK_MS = 10 * 60 * 1000;
 
     private static final String TAG = MedtronicCnlIntentService.class.getSimpleName();
 
@@ -84,7 +93,7 @@ public class MedtronicCnlIntentService extends IntentService {
     private DataStore dataStore = DataStore.getInstance();
     private ConfigurationStore configurationStore = ConfigurationStore.getInstance();
     private DateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss", Locale.US);
-    private DateFormat dateFormatterNote = new SimpleDateFormat("HH:mm", Locale.US);
+    private DateFormat dateFormatterNote = new SimpleDateFormat("E HH:mm", Locale.US);
     private Realm realm;
     private long pumpOffset;
 
@@ -153,6 +162,7 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
         Log.d(TAG, "onHandleIntent called");
         try {
             final long timePollStarted = System.currentTimeMillis();
+            long pollInterval = configurationStore.getPollInterval();
             realm = Realm.getDefaultInstance();
 
             long due = checkPollTime();
@@ -162,21 +172,6 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                 return;
             }
 
-            RealmResults<PumpStatusEvent> pumpresults = realm.where(PumpStatusEvent.class)
-                    .greaterThan("eventDate", new Date(System.currentTimeMillis() - (6 * 60 * 60 * 1000)))
-                    .findAllSorted("eventDate", Sort.DESCENDING);
-            long pollInterval = configurationStore.getPollInterval();
-            if (pumpresults.size() > 0) {
-                short pumpBatteryLevel = pumpresults.first().getBatteryPercentage();
-                if ((pumpBatteryLevel > 0) && (pumpBatteryLevel <= 25)) {
-                    pollInterval = configurationStore.getLowBatteryPollInterval();
-                    sendStatus(ICON_WARN + "Warning: pump battery low");
-                    if (pollInterval != configurationStore.getPollInterval()) {
-                        sendStatus(ICON_SETTING + "Low battery poll interval: " + (pollInterval / 60000) + " minutes");
-                    }
-                }
-            }
-
             // TODO - throw, don't return
             if (!openUsbDevice())
                 return;
@@ -243,14 +238,14 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                         sendStatus(ICON_WARN + "Could not communicate with the pump. Is it nearby?");
                         Log.i(TAG, "Could not communicate with the pump. Is it nearby?");
                         dataStore.incCommsConnectError();
-                        pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available
+                        pollInterval = POLL_PERIOD_MS / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available
                     } else if (cnlReader.getPumpSession().getRadioRSSIpercentage() < 5) {
                         sendStatus(String.format(Locale.getDefault(), "Connected on channel %d  RSSI: %d%%", (int) radioChannel, cnlReader.getPumpSession().getRadioRSSIpercentage()));
                         sendStatus(ICON_WARN + "Warning: pump signal too weak. Is it nearby?");
                         Log.i(TAG, "Warning: pump signal too weak. Is it nearby?");
                         dataStore.incCommsConnectError();
                         dataStore.incCommsSignalError();
-                        pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available
+                        pollInterval = POLL_PERIOD_MS / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available
                     } else {
                         dataStore.decCommsConnectError();
                         if (cnlReader.getPumpSession().getRadioRSSIpercentage() < 20)
@@ -273,14 +268,19 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                         // TODO - this should not be necessary. We should reverse lookup the device name from PumpInfo
                         pumpRecord.setDeviceName(deviceName);
 
+                        if (radioChannel == 26) cnlReader.beginEHSMSession(); // gentle persuasion to leave channel 26 (weakest for CNL and causes Pebble to lose BT often) by using EHSM to influence pump channel change
+
                         long pumpTime = cnlReader.getPumpTime().getTime();
                         pumpOffset = pumpTime - System.currentTimeMillis();
                         Log.d(TAG, "Time offset between pump and device: " + pumpOffset + " millis.");
 
                         pumpRecord.setPumpTimeOffset(pumpOffset);
                         pumpRecord.setPumpDate(new Date(pumpTime));
+                        pumpRecord.setEventDate(new Date(System.currentTimeMillis()));
                         cnlReader.updatePumpStatus(pumpRecord);
 
+                        if (radioChannel == 26) cnlReader.endEHSMSession();
+
                         validatePumpRecord(pumpRecord, activePump);
                         activePump.getPumpHistory().add(pumpRecord);
                         realm.commitTransaction();
@@ -288,6 +288,13 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                         dataStore.incCommsSuccess();
                         dataStore.clearCommsError();
 
+                        if (pumpRecord.getBatteryPercentage() <= 25) {
+                            dataStore.incPumpBatteryError();
+                            pollInterval = configurationStore.getLowBatteryPollInterval();
+                        } else {
+                            dataStore.clearPumpBatteryError();
+                        }
+
                         if (pumpRecord.isCgmActive()) {
                             dataStore.clearPumpCgmNA(); // poll clash detection
                             dataStore.clearPumpLostSensorError();
@@ -296,30 +303,38 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                                 sendStatus(ICON_CGM + "sensor is in warm-up phase");
                             else if (pumpRecord.getCalibrationDueMinutes() == 0)
                                 sendStatus(ICON_CGM + "sensor calibration is due now!");
+                            else if (pumpRecord.getSgv() == 0 && pumpRecord.isCgmCalibrating())
+                                sendStatus(ICON_CGM + "sensor is calibrating");
                             else if (pumpRecord.getSgv() == 0)
                                 sendStatus(ICON_CGM + "sensor error (pump graph gap)");
                             else {
                                 dataStore.incCommsSgvSuccess();
+                                // TODO - don't convert SGV here, convert dynamically in ui status message handler
                                 sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv())
                                         + "  At: " + dateFormatter.format(pumpRecord.getCgmDate().getTime())
                                         + "  Pump: " + (pumpOffset > 0 ? "+" : "") + (pumpOffset / 1000L) + "sec");
+                                if (pumpRecord.isCgmCalibrating())
+                                    sendStatus(ICON_CGM + "sensor is calibrating");
                                 if (pumpRecord.isOldSgvWhenNewExpected()) {
-                                    sendStatus(ICON_WARN + "Pump sent old SGV event");
+                                    sendStatus(ICON_CGM + "old SGV event received");
                                     // pump may have missed sensor transmission or be delayed in posting to status message
                                     // in most cases the next scheduled poll will have latest sgv, occasionally it is available this period after a delay
                                     // if user selects double poll option we try again this period or wait until next
-                                    pollInterval = POLL_PERIOD_MS / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L);
+                                    pollInterval = configurationStore.isReducePollOnPumpAway() ? 60000 : POLL_PERIOD_MS;
                                 }
                             }
 
                         } else {
-                            sendStatus(ICON_CGM + "cgm n/a (pump lost sensor)");
                             dataStore.incPumpCgmNA(); // poll clash detection
-                            if (dataStore.getCommsSgvSuccess() > 0) // only count errors if cgm is being used
-                                dataStore.incPumpLostSensorError();
+                            if (dataStore.getCommsSgvSuccess() > 0) {
+                                dataStore.incPumpLostSensorError(); // only count errors if cgm is being used
+                                sendStatus(ICON_CGM + "cgm n/a (pump lost sensor)");
+                            } else {
+                                sendStatus(ICON_CGM + "cgm n/a");
+                            }
                         }
 
-                        sendStatusTreatments(pumpRecord);
+                        sendStatusNotifications(pumpRecord);
 
                         // Tell the Main Activity we have new data
                         sendMessage(Constants.ACTION_UPDATE_PUMP);
@@ -366,32 +381,29 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                 Log.e(TAG, "Could not close connection.", e);
                 sendStatus(ICON_WARN + "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();
-                    }
-                    RemoveOutdatedRecords();
-
-                    long nextpoll = requestPollTime(timePollStarted, pollInterval);
-                    MedtronicCnlAlarmManager.setAlarm(nextpoll);
-                    sendStatus("Next poll due at: " + dateFormatter.format(nextpoll));
-
-                    realm.close();
+                if (realm.isInTransaction()) {
+                    // If we didn't commit the transaction, we've run into an error. Let's roll it back
+                    realm.cancelTransaction();
                 }
 
+                long nextpoll = requestPollTime(timePollStarted, pollInterval);
+                MedtronicCnlAlarmManager.setAlarm(nextpoll);
+                sendStatus("Next poll due at: " + dateFormatter.format(nextpoll));
+
+                RemoveOutdatedRecords();
                 uploadPollResults();
                 sendStatusWarnings();
             }
 
         } finally {
+            if (!realm.isClosed()) realm.close();
             MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
         }
     }
 
-    private void sendStatusTreatments(PumpStatusEvent pumpRecord) {
+    private void sendStatusNotifications(PumpStatusEvent pumpRecord) {
         if (pumpRecord.isValidBGL())
+            // TODO - don't convert BGL here, convert dynamically in ui status message handler
             sendStatus(ICON_BGL + "Recent finger BG: " + MainActivity.strFormatSGV(pumpRecord.getRecentBGL()));
 
         if (pumpRecord.isValidBolus()) {
@@ -409,20 +421,35 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
             else if (pumpRecord.getTempBasalMinutesRemaining() > 0)
                 sendStatus(ICON_BASAL + "Temp basal: " + pumpRecord.getTempBasalRate() + "u Remaining: " + pumpRecord.getTempBasalMinutesRemaining() + " minutes");
             else
-                sendStatus(ICON_BASAL + "Temp basal stopped");
+                sendStatus(ICON_BASAL + "Temp basal: stopped before expected duration");
         }
 
+        if (pumpRecord.isValidSUSPEND())
+            sendStatus(ICON_SUSPEND + "Pump suspended insulin delivery approx: " + dateFormatterNote.format(pumpRecord.getSuspendAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getSuspendBeforeDate()));
+        if (pumpRecord.isValidSUSPENDOFF())
+            sendStatus(ICON_RESUME + "Pump resumed insulin delivery approx: " + dateFormatterNote.format(pumpRecord.getSuspendAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getSuspendBeforeDate()));
+
         if (pumpRecord.isValidSAGE())
-            sendStatus(ICON_NOTE + "Sensor changed approx: " + dateFormatterNote.format(pumpRecord.getSageAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getSageBeforeDate()));
+            sendStatus(ICON_CHANGE + "Sensor changed approx: " + dateFormatterNote.format(pumpRecord.getSageAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getSageBeforeDate()));
         if (pumpRecord.isValidCAGE())
-            sendStatus(ICON_NOTE + "Reservoir changed approx: " + dateFormatterNote.format(pumpRecord.getCageAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getCageBeforeDate()));
+            sendStatus(ICON_CHANGE + "Reservoir changed approx: " + dateFormatterNote.format(pumpRecord.getCageAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getCageBeforeDate()));
         if (pumpRecord.isValidBATTERY())
-            sendStatus(ICON_NOTE + "Pump battery changed approx: " + dateFormatterNote.format(pumpRecord.getBatteryAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getBatteryBeforeDate()));
+            sendStatus(ICON_CHANGE + "Pump battery changed approx: " + dateFormatterNote.format(pumpRecord.getBatteryAfterDate()) + " - " + dateFormatterNote.format(pumpRecord.getBatteryBeforeDate()));
+
+        if (pumpRecord.isValidALERT())
+            sendStatus(ICON_BELL + "Active alert on pump At: " + dateFormatter.format(pumpRecord.getAlertDate()));
     }
 
     private void sendStatusWarnings() {
 
-        if (Math.abs(pumpOffset) > 10 * 60 * 1000)
+        if (dataStore.getPumpBatteryError() >= ERROR_PUMPBATTERY_AT) {
+            dataStore.clearPumpBatteryError();
+            sendStatus(ICON_WARN + "Warning: pump battery low");
+            if (configurationStore.getLowBatteryPollInterval() != configurationStore.getPollInterval())
+                sendStatus(ICON_SETTING + "Low battery poll interval: " + (configurationStore.getLowBatteryPollInterval() / 60000) + " minutes");
+        }
+
+        if (Math.abs(pumpOffset) > ERROR_PUMPCLOCK_MS)
             dataStore.incPumpClockError();
         if (dataStore.getPumpClockError() >= ERROR_PUMPCLOCK_AT) {
             dataStore.clearPumpClockError();
@@ -430,20 +457,24 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                     + " Pump is over " + (Math.abs(pumpOffset) / 60000L) + " minutes " + (pumpOffset > 0 ? "ahead" : "behind") + " of time used by uploader.");
             sendStatus(ICON_HELP + "The uploader phone/device should have the current time provided by network. Pump clock drifts forward and needs to be set to correct time occasionally.");
         }
+
         if (dataStore.getCommsError() >= ERROR_COMMS_AT) {
             sendStatus(ICON_WARN + "Warning: multiple comms/timeout errors detected.");
             sendStatus(ICON_HELP + "Try: disconnecting and reconnecting the Contour Next Link to phone / restarting phone / check pairing of CNL with Pump.");
         }
+
         if (dataStore.getPumpLostSensorError() >= ERROR_PUMPLOSTSENSOR_AT) {
             dataStore.clearPumpLostSensorError();
             sendStatus(ICON_WARN + "Warning: SGV is unavailable from pump often. The pump is missing transmissions from the sensor.");
             sendStatus(ICON_HELP + "Keep pump on same side of body as sensor. Avoid using body sensor locations that can block radio signal.");
         }
+
         if (dataStore.getCommsConnectError() >= ERROR_CONNECT_AT * (configurationStore.isReducePollOnPumpAway() ? 2 : 1)) {
             dataStore.clearCommsConnectError();
             sendStatus(ICON_WARN + "Warning: connecting to pump is failing often.");
             sendStatus(ICON_HELP + "Keep pump nearby to uploader phone/device. The body can block radio signals between pump and uploader.");
         }
+
         if (dataStore.getCommsSignalError() >= ERROR_SIGNAL_AT) {
             dataStore.clearCommsSignalError();
             sendStatus(ICON_WARN + "Warning: RSSI radio signal from pump is generally weak and may increase errors.");
@@ -452,30 +483,37 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
     }
 
     private void RemoveOutdatedRecords() {
-        final RealmResults<PumpStatusEvent> resultsx =
+        final RealmResults<PumpStatusEvent> results =
                 realm.where(PumpStatusEvent.class)
                         .lessThan("eventDate", new Date(System.currentTimeMillis() - (48 * 60 * 60 * 1000)))
                         .findAll();
 
-        if (resultsx.size() > 0) {
+        if (results.size() > 0) {
             realm.executeTransaction(new Realm.Transaction() {
                 @Override
                 public void execute(Realm realm) {
                     // Delete all matches
-                    Log.d(TAG, "Deleting " + resultsx.size() + " records from realm");
-                    resultsx.deleteAllFromRealm();
+                    Log.d(TAG, "Deleting " + results.size() + " records from realm");
+                    results.deleteAllFromRealm();
                 }
             });
         }
     }
 
-// TODO fix square/dual bolus time after battery change as pump resets start time, use refs to work out actual time and duration?
-// TODO for NS add temp basal at 0% when suspended? use 30 or 60 min blocks and cancel temp when resumed?
-// TODO check on optimal use of Realm search+results as we make heavy use for validation
+    // TODO - check on optimal use of Realm search+results as we make heavy use for validation
 
     private void validatePumpRecord(PumpStatusEvent pumpRecord, PumpInfo activePump) {
 
-        // TODO cgm/sgv validation - handle sensor exceptions
+        int index;
+        Date uploaderStartDate = dataStore.getUploaderStartDate();
+
+        // TODO - pump validation is unused but will allow for future record manipulation when adding data from pump history message (gap fill)
+
+        // validate that this contains a new PUMP record
+        pumpRecord.setValidPUMP(true);
+
+        // TODO - cgm validation - handle sensor exceptions
+
         // validate that this contains a new CGM record
         if (pumpRecord.isCgmActive()) {
             pumpRecord.setValidCGM(true);
@@ -508,6 +546,8 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
             }
         }
 
+        // TODO - square/dual stopped and new bolus started between poll snapshots, check realm history to handle this?
+
         // validate that this contains a new BOLUS record
         RealmResults<PumpStatusEvent> lastbolus_results = activePump.getPumpHistory()
                 .where()
@@ -517,29 +557,42 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                 .findAll();
 
         if (lastbolus_results.size() == 0) {
-            pumpRecord.setValidBolus(true);
-
-            if (pumpRecord.getBolusingReference() == pumpRecord.getLastBolusReference()
-                    && pumpRecord.getBolusingMinutesRemaining() > 10) {
-                pumpRecord.setValidBolusDual(true);
-            }
 
             RealmResults<PumpStatusEvent> bolusing_results = activePump.getPumpHistory()
                     .where()
                     .equalTo("bolusingReference", pumpRecord.getLastBolusReference())
-                    .greaterThan("bolusingMinutesRemaining", 10)
+                    .greaterThan("bolusingMinutesRemaining", 10)   // if a manual normal bolus referred to here while square is being delivered it will show the remaining time for all bolusing
                     .findAllSorted("eventDate", Sort.ASCENDING);
 
-            // note: if pump battery is changed during square/dual bolus period the last bolus time will be set to this time (pump asks user to resume/cancel bolus)
-
             if (bolusing_results.size() > 0) {
-                pumpRecord.setValidBolusSquare(true);
                 long start = pumpRecord.getLastBolusPumpDate().getTime();
+                long start_bolusing = bolusing_results.first().getPumpDate().getTime();
+
+                // if pump battery is changed during square/dual bolus period the last bolus time will be set to this time (pump asks user to resume/cancel bolus)
+                // use bolusing start time when this is detected
+                if (start - start_bolusing > 10 * 60)
+                    start = start_bolusing;
+
                 long end = pumpRecord.getPumpDate().getTime();
-                long duration = bolusing_results.first().getPumpDate().getTime() - start + (bolusing_results.first().getBolusingMinutesRemaining() * 60000);
+                long duration = start_bolusing - start + (bolusing_results.first().getBolusingMinutesRemaining() * 60000);
                 if (start + duration > end) // was square bolus stopped before expected duration?
                     duration = end - start;
-                pumpRecord.setLastBolusDuration((short) (duration / 60000));
+
+                // check that this was a square bolus and not a normal bolus
+                if (duration > 10) {
+                    pumpRecord.setValidBolus(true);
+                    pumpRecord.setValidBolusSquare(true);
+                    pumpRecord.setLastBolusDate(new Date (start));
+                    pumpRecord.setLastBolusDuration((short) (duration / 60000));
+                }
+            }
+
+            else if (pumpRecord.getLastBolusDate().getTime() >= uploaderStartDate.getTime()) {
+                pumpRecord.setValidBolus(true);
+                if (pumpRecord.getBolusingReference() == pumpRecord.getLastBolusReference()
+                        && pumpRecord.getBolusingMinutesRemaining() > 10) {
+                    pumpRecord.setValidBolusDual(true);
+                }
             }
         }
 
@@ -550,7 +603,7 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                 .greaterThan("eventDate", new Date(System.currentTimeMillis() - (24 * 60 * 60 * 1000)))
                 .findAllSorted("eventDate", Sort.DESCENDING);
         if (pumpRecord.getTempBasalMinutesRemaining() > 0) {
-            int index = 0;
+            index = 0;
             if (tempbasal_results.size() > 1) {
                 short minutes = pumpRecord.getTempBasalMinutesRemaining();
                 for (index = 0; index < tempbasal_results.size(); index++) {
@@ -568,6 +621,7 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                         tempbasal_results.get(index).getTempBasalRate() != pumpRecord.getTempBasalRate()) {
                     pumpRecord.setValidTEMPBASAL(true);
                     pumpRecord.setTempBasalAfterDate(tempbasal_results.get(index).getEventDate());
+                    pumpRecord.setTempBasalBeforeDate(pumpRecord.getEventDate());
                 }
         } else {
             // check if stopped before expected duration
@@ -575,7 +629,67 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                 if (pumpRecord.getPumpDate().getTime() - tempbasal_results.first().getPumpDate().getTime() - (tempbasal_results.first().getTempBasalMinutesRemaining() * 60 * 1000) < -60 * 1000) {
                     pumpRecord.setValidTEMPBASAL(true);
                     pumpRecord.setTempBasalAfterDate(tempbasal_results.first().getEventDate());
+                    pumpRecord.setTempBasalBeforeDate(pumpRecord.getEventDate());
+                }
+        }
+
+        // validate that this contains a new SUSPEND record
+        RealmResults<PumpStatusEvent> suspend_results =  activePump.getPumpHistory()
+                .where()
+                .greaterThan("eventDate", new Date(System.currentTimeMillis() - (2 * 60 * 60 * 1000)))
+                .equalTo("validSUSPEND", true)
+                .or()
+                .equalTo("validSUSPENDOFF", true)
+                .findAllSorted("eventDate", Sort.DESCENDING);
+
+        if (suspend_results.size() > 0) {
+            // new valid suspend - set temp basal for 0u 60m in NS
+            if (pumpRecord.isSuspended() && suspend_results.first().isValidSUSPENDOFF()) {
+                pumpRecord.setValidSUSPEND(true);
+            }
+            // continuation valid suspend every 30m - set temp basal for 0u 60m in NS
+            else if (pumpRecord.isSuspended() && suspend_results.first().isValidSUSPEND() &&
+                    pumpRecord.getEventDate().getTime() - suspend_results.first().getEventDate().getTime() >= 30 * 60 * 1000) {
+                pumpRecord.setValidSUSPEND(true);
+            }
+            // valid suspendoff - set temp stopped in NS
+            else if (!pumpRecord.isSuspended() && suspend_results.first().isValidSUSPEND() &&
+                    pumpRecord.getEventDate().getTime() - suspend_results.first().getEventDate().getTime() <= 60 * 60 * 1000) {
+                pumpRecord.setValidSUSPENDOFF(true);
+                RealmResults<PumpStatusEvent> suspendended_results =  activePump.getPumpHistory()
+                        .where()
+                        .greaterThan("eventDate", new Date(System.currentTimeMillis() - (2 * 60 * 60 * 1000)))
+                        .findAllSorted("eventDate", Sort.DESCENDING);
+                pumpRecord.setSuspendAfterDate(suspendended_results.first().getEventDate());
+                pumpRecord.setSuspendBeforeDate(pumpRecord.getEventDate());
+            }
+        }
+        else if (pumpRecord.isSuspended()) {
+            pumpRecord.setValidSUSPEND(true);
+        }
+
+        // absolute suspend start time approx to after-before range
+        if (pumpRecord.isValidSUSPEND()) {
+            RealmResults<PumpStatusEvent> suspendstarted_results =  activePump.getPumpHistory()
+                    .where()
+                    .greaterThan("eventDate", new Date(System.currentTimeMillis() - (12 * 60 * 60 * 1000)))
+                    .findAllSorted("eventDate", Sort.ASCENDING);
+            index = suspendstarted_results.size();
+            if (index > 0) {
+                while (index > 0) {
+                    index--;
+                    if (!suspendstarted_results.get(index).isSuspended())
+                        break;
                 }
+                pumpRecord.setSuspendAfterDate(suspendstarted_results.get(index).getEventDate());
+            }
+            else {
+                pumpRecord.setSuspendAfterDate(pumpRecord.getEventDate());
+            }
+            if (++index < suspendstarted_results.size())
+                pumpRecord.setSuspendBeforeDate(suspendstarted_results.get(index).getEventDate());
+            else
+                pumpRecord.setSuspendBeforeDate(pumpRecord.getEventDate());
         }
 
         // validate that this contains a new SAGE record
@@ -589,18 +703,18 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
                 pumpRecord.setValidSAGE(true);
                 RealmResults<PumpStatusEvent> sagedate_results = activePump.getPumpHistory()
                         .where()
-                        .greaterThan("eventDate", new Date(System.currentTimeMillis() - (12 * 60 * 1000)))
+                        .greaterThan("eventDate", new Date(System.currentTimeMillis() - (6 * 60 * 60 * 1000)))
                         .findAllSorted("eventDate", Sort.DESCENDING);
                 pumpRecord.setSageAfterDate(sagedate_results.first().getEventDate());
                 pumpRecord.setSageBeforeDate(pumpRecord.getEventDate());
             }
-        } else if (pumpRecord.isCgmActive() && pumpRecord.getTransmitterBattery() > 70) {
-            // note: transmitter battery can fluctuate when on the edge of a state change, usually low battery
+        } else if (pumpRecord.isCgmActive() && pumpRecord.getTransmitterBattery() == 100) {
+            // note: transmitter battery can fluctuate when on the edge of a state change
             RealmResults<PumpStatusEvent> sagebattery_results = activePump.getPumpHistory()
                     .where()
-                    .greaterThan("eventDate", new Date(System.currentTimeMillis() - (12 * 60 * 60 * 1000)))
+                    .greaterThan("eventDate", new Date(System.currentTimeMillis() - (6 * 60 * 60 * 1000)))
                     .equalTo("cgmActive", true)
-                    .lessThan("transmitterBattery", pumpRecord.getTransmitterBattery())
+                    .lessThan("transmitterBattery", 50)
                     .findAllSorted("eventDate", Sort.DESCENDING);
             if (sagebattery_results.size() > 0) {
                 RealmResults<PumpStatusEvent> sage_valid_results = activePump.getPumpHistory()
@@ -619,7 +733,7 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
         // validate that this contains a new CAGE record
         RealmResults<PumpStatusEvent> cage_results = activePump.getPumpHistory()
                 .where()
-                .greaterThan("eventDate", new Date(System.currentTimeMillis() - (12 * 60 * 60 * 1000)))
+                .greaterThan("eventDate", new Date(System.currentTimeMillis() - (6 * 60 * 60 * 1000)))
                 .lessThan("reservoirAmount", pumpRecord.getReservoirAmount())
                 .findAllSorted("eventDate", Sort.DESCENDING);
         if (cage_results.size() > 0) {
@@ -638,7 +752,7 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
         // validate that this contains a new BATTERY record
         RealmResults<PumpStatusEvent> battery_results = activePump.getPumpHistory()
                 .where()
-                .greaterThan("eventDate", new Date(System.currentTimeMillis() - (12 * 60 * 60 * 1000)))
+                .greaterThan("eventDate", new Date(System.currentTimeMillis() - (6 * 60 * 60 * 1000)))
                 .lessThan("batteryPercentage", pumpRecord.getBatteryPercentage())
                 .findAllSorted("eventDate", Sort.DESCENDING);
         if (battery_results.size() > 0) {
@@ -654,6 +768,18 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
             }
         }
 
+        // validate that this contains a new ALERT record
+        if (pumpRecord.getAlert() > 0) {
+            RealmResults<PumpStatusEvent> alert_results = activePump.getPumpHistory()
+                    .where()
+                    .greaterThan("eventDate", new Date(System.currentTimeMillis() - (6 * 60 * 60 * 1000)))
+                    .findAllSorted("eventDate", Sort.DESCENDING);
+            if (alert_results.size() > 0) {
+                if (alert_results.first().getAlert() != pumpRecord.getAlert())
+                    pumpRecord.setValidALERT(true);
+            }
+        }
+
     }
 
     // pollInterval: default = POLL_PERIOD_MS (time to pump cgm reading)
@@ -692,8 +818,8 @@ CNL: unpaired PUMP: unpaired UPLOADER: unregistered = "Invalid message received
 
         if (timeLastCGM == 0)
             nextRequestedPollTime += 15 * 1000; // push poll time forward to avoid potential clash when no previous poll time available to sync with
-        else if (pumpCgmNA > 2)
-            nextRequestedPollTime += ((pumpCgmNA - 2) % 3) * 30 * 1000; // adjust poll time in 30 second steps to avoid potential poll clash (adjustment: poll+30s / poll+60s / poll+0s)
+        else if (pumpCgmNA >= POLL_ANTI_CLASH)
+            nextRequestedPollTime += (((pumpCgmNA - POLL_ANTI_CLASH) % 3) + 1) * 30 * 1000; // adjust poll time in 30 second steps to avoid potential poll clash (adjustment: poll+30s / poll+60s / poll+90s)
 
         // check if requested poll time is too close to next actual poll time
         if (nextRequestedPollTime > nextActualPollTime - POLL_GRACE_PERIOD_MS - POLL_PRE_GRACE_PERIOD_MS
diff --git a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
index 84b694314657ba3a50f16c5ecb189c8c6d165226..f0d9469626756391b0e1eea41125528b65cfa8e1 100644
--- a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
+++ b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
@@ -58,7 +58,6 @@ public class PumpStatusEvent extends RealmObject {
     private float lastBolusAmount;
     private Date lastBolusDate;
     private Date lastBolusPumpDate;
-    private byte lastBolusType;
     private short lastBolusDuration;
     private short lastBolusReference;
     private byte transmitterBattery;
@@ -66,18 +65,23 @@ public class PumpStatusEvent extends RealmObject {
     private short calibrationDueMinutes;
     private float sensorRateOfChange;
 
+    private boolean oldSgvWhenNewExpected = false;
+
+    private boolean validPUMP = false;
     private boolean validCGM = false;
     private boolean validSGV = false;
     private boolean validBGL = false;
     private boolean validBolus = false;
     private boolean validBolusDual = false;
     private boolean validBolusSquare = false;
-    private boolean validAlert = false;
-
-    private boolean oldSgvWhenNewExpected = false;
-
+    private boolean validALERT = false;
+    private boolean validSUSPEND = false;
+    private boolean validSUSPENDOFF = false;
+    private Date suspendAfterDate;
+    private Date suspendBeforeDate;
     private boolean validTEMPBASAL = false;
     private Date tempBasalAfterDate;
+    private Date tempBasalBeforeDate;
     private boolean validCAGE = false;
     private Date cageAfterDate;
     private Date cageBeforeDate;
@@ -96,12 +100,14 @@ public class PumpStatusEvent extends RealmObject {
         this.eventDate = new Date();
     }
 
+    public void setEventDate(Date eventDate) {
+        this.eventDate = eventDate;
+    }
+
     public Date getEventDate() {
         return eventDate;
     }
 
-    // No EventDate setter. The eventDate is set at the time that the PumpStatusEvent is created.
-
     public Date getPumpDate() {
         return pumpDate;
     }
@@ -201,6 +207,14 @@ public class PumpStatusEvent extends RealmObject {
         this.oldSgvWhenNewExpected = oldSgvWhenNewExpected;
     }
 
+    public boolean isValidPUMP() {
+        return validPUMP;
+    }
+
+    public void setValidPUMP(boolean validPUMP) {
+        this.validPUMP = validPUMP;
+    }
+
     public boolean isValidCGM() {
         return validCGM;
     }
@@ -249,14 +263,47 @@ public class PumpStatusEvent extends RealmObject {
         this.validBolusSquare = validBolusSquare;
     }
 
-    public boolean isValidAlert() {
-        return validAlert;
+    public boolean isValidALERT() {
+        return validALERT;
+    }
+
+    public void setValidALERT(boolean validALERT) {
+        this.validALERT = validALERT;
+    }
+
+    public boolean isValidSUSPEND() {
+        return validSUSPEND;
+    }
+
+    public void setValidSUSPEND(boolean validSUSPEND) {
+        this.validSUSPEND = validSUSPEND;
+    }
+
+    public boolean isValidSUSPENDOFF() {
+        return validSUSPENDOFF;
     }
 
-    public void setValidAlert(boolean validAlert) {
-        this.validAlert = validAlert;
+    public void setValidSUSPENDOFF(boolean validSUSPENDOFF) {
+        this.validSUSPENDOFF = validSUSPENDOFF;
     }
 
+    public Date getSuspendAfterDate() {
+        return suspendAfterDate;
+    }
+
+    public void setSuspendAfterDate(Date suspendAfterDate) {
+        this.suspendAfterDate = suspendAfterDate;
+    }
+
+    public Date getSuspendBeforeDate() {
+        return suspendBeforeDate;
+    }
+
+    public void setSuspendBeforeDate(Date suspendBeforeDate) {
+        this.suspendBeforeDate = suspendBeforeDate;
+    }
+
+
     public boolean isValidTEMPBASAL() {
         return validTEMPBASAL;
     }
@@ -273,6 +320,14 @@ public class PumpStatusEvent extends RealmObject {
         this.tempBasalAfterDate = tempBasalAfterDate;
     }
 
+    public Date getTempBasalBeforeDate() {
+        return tempBasalBeforeDate;
+    }
+
+    public void setTempBasalBeforeDate(Date tempBasalBeforeDate) {
+        this.tempBasalBeforeDate = tempBasalBeforeDate;
+    }
+
     public boolean isValidCAGE() {
         return validCAGE;
     }
@@ -625,14 +680,6 @@ public class PumpStatusEvent extends RealmObject {
         this.lastBolusReference = lastBolusReference;
     }
 
-    public byte getLastBolusType() {
-        return lastBolusType;
-    }
-
-    public void setLastBolusType(byte lastBolusType) {
-        this.lastBolusType = lastBolusType;
-    }
-
     public short getLastBolusDuration() {
         return lastBolusDuration;
     }
@@ -713,26 +760,35 @@ public class PumpStatusEvent extends RealmObject {
                 ", recentBGL=" + recentBGL +
                 ", alert=" + alert +
                 ", alertDate=" + alertDate +
+                ", alertPumpDate=" + alertPumpDate +
                 ", bolusingDelivered=" + bolusingDelivered +
                 ", bolusingMinutesRemaining=" + bolusingMinutesRemaining +
                 ", bolusingReference=" + bolusingReference +
                 ", lastBolusAmount=" + lastBolusAmount +
                 ", lastBolusDate=" + lastBolusDate +
+                ", lastBolusPumpDate=" + lastBolusPumpDate +
+                ", lastBolusDuration=" + lastBolusDuration +
                 ", lastBolusReference=" + lastBolusReference +
                 ", transmitterBattery=" + transmitterBattery +
                 ", transmitterControl=" + transmitterControl +
                 ", calibrationDueMinutes=" + calibrationDueMinutes +
                 ", sensorRateOfChange=" + sensorRateOfChange +
+                ", oldSgvWhenNewExpected=" + oldSgvWhenNewExpected +
+                ", validPUMP=" + validPUMP +
                 ", validCGM=" + validCGM +
                 ", validSGV=" + validSGV +
                 ", validBGL=" + validBGL +
                 ", validBolus=" + validBolus +
                 ", validBolusDual=" + validBolusDual +
                 ", validBolusSquare=" + validBolusSquare +
-                ", validAlert=" + validAlert +
-                ", oldSgvWhenNewExpected=" + oldSgvWhenNewExpected +
+                ", validALERT=" + validALERT +
+                ", validSUSPEND=" + validSUSPEND +
+                ", validSUSPENDOFF=" + validSUSPENDOFF +
+                ", suspendAfterDate=" + suspendAfterDate +
+                ", suspendBeforeDate=" + suspendBeforeDate +
                 ", validTEMPBASAL=" + validTEMPBASAL +
                 ", tempBasalAfterDate=" + tempBasalAfterDate +
+                ", tempBasalBeforeDate=" + tempBasalBeforeDate +
                 ", validCAGE=" + validCAGE +
                 ", cageAfterDate=" + cageAfterDate +
                 ", cageBeforeDate=" + cageBeforeDate +
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java
index 0ce75df8e8be4b12119b3f33c8f676514dbb5bec..06f7f79eccf7b415c588be5e9a65e966f5cf113a 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java
@@ -14,15 +14,16 @@ import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer;
 
 import android.support.annotation.NonNull;
 
+import info.nightscout.android.utils.ConfigurationStore;
 import info.nightscout.api.UploadApi;
-import info.nightscout.api.GlucoseEndpoints;
-import info.nightscout.api.GlucoseEndpoints.GlucoseEntry;
-import info.nightscout.api.BolusEndpoints;
-import info.nightscout.api.BolusEndpoints.BolusEntry;
+import info.nightscout.api.SgvEndpoints;
+import info.nightscout.api.SgvEndpoints.SgvEntry;
+import info.nightscout.api.MbgEndpoints;
+import info.nightscout.api.MbgEndpoints.MbgEntry;
 import info.nightscout.api.TreatmentEndpoints;
 import info.nightscout.api.TreatmentEndpoints.TreatmentEntry;
-import info.nightscout.api.TempBasalAbsoluteEndpoints.TempBasalAbsoluteEntry;
-import info.nightscout.api.TempBasalAbsoluteEndpoints;
+import info.nightscout.api.TempBasalRateEndpoints.TempBasalRateEntry;
+import info.nightscout.api.TempBasalRateEndpoints;
 import info.nightscout.api.TempBasalPercentEndpoints;
 import info.nightscout.api.TempBasalPercentEndpoints.TempBasalPercentEntry;
 import info.nightscout.api.TempBasalCancelEndpoints;
@@ -38,6 +39,8 @@ import info.nightscout.api.DeviceEndpoints.DeviceStatus;
 import okhttp3.ResponseBody;
 import retrofit2.Response;
 
+import static info.nightscout.android.medtronic.MainActivity.MMOLXLFACTOR;
+
 class NightScoutUpload {
 
     private static final String TAG = NightscoutUploadIntentService.class.getSimpleName();
@@ -50,27 +53,29 @@ class NightScoutUpload {
 
     boolean doRESTUpload(String url,
                          String secret,
+                         boolean treatments,
                          int uploaderBatteryLevel,
                          List<PumpStatusEvent> records) throws Exception {
-        return isUploaded(records, url, secret, uploaderBatteryLevel);
+        return isUploaded(records, url, secret, treatments, uploaderBatteryLevel);
     }
 
     private boolean isUploaded(List<PumpStatusEvent> records,
                                String baseURL,
                                String secret,
+                               boolean treatments,
                                int uploaderBatteryLevel) throws Exception {
 
         UploadApi uploadApi = new UploadApi(baseURL, formToken(secret));
 
         boolean eventsUploaded = uploadEvents(
-                uploadApi.getGlucoseEndpoints(),
-                uploadApi.getBolusEndpoints(),
+                uploadApi.getSgvEndpoints(),
+                uploadApi.getMbgEndpoints(),
                 uploadApi.getTreatmentEndpoints(),
-                uploadApi.getTempBasalAbsoluteEndpoints(),
+                uploadApi.getTempBasalRateEndpoints(),
                 uploadApi.getTempBasalPercentEndpoints(),
                 uploadApi.getTempBasalCancelEndpoints(),
                 uploadApi.getNoteEndpoints(),
-                records);
+                records, treatments);
 
         boolean deviceStatusUploaded = uploadDeviceStatus(uploadApi.getDeviceEndpoints(),
                 uploaderBatteryLevel, records);
@@ -78,20 +83,21 @@ class NightScoutUpload {
         return eventsUploaded && deviceStatusUploaded;
     }
 
-    private boolean uploadEvents(GlucoseEndpoints glucoseEndpoints,
-                                 BolusEndpoints bolusEndpoints,
+    private boolean uploadEvents(SgvEndpoints sgvEndpoints,
+                                 MbgEndpoints mbgEndpoints,
                                  TreatmentEndpoints treatmentEndpoints,
-                                 TempBasalAbsoluteEndpoints tempBasalAbsoluteEndpoints,
+                                 TempBasalRateEndpoints tempBasalRateEndpoints,
                                  TempBasalPercentEndpoints tempBasalPercentEndpoints,
                                  TempBasalCancelEndpoints tempBasalCancelEndpoints,
                                  NoteEndpoints noteEndpoints,
-                                 List<PumpStatusEvent> records) throws Exception {
+                                 List<PumpStatusEvent> records,
+                                 boolean treatments) throws Exception {
 
 
-        List<GlucoseEntry> glucoseEntries = new ArrayList<>();
-        List<BolusEntry> bolusEntries = new ArrayList<>();
+        List<SgvEntry> sgvEntries = new ArrayList<>();
+        List<MbgEntry> mbgEntries = new ArrayList<>();
         List<TreatmentEntry> treatmentEntries = new ArrayList<>();
-        List<TempBasalAbsoluteEntry> tempBasalAbsoluteEntries = new ArrayList<>();
+        List<TempBasalRateEntry> tempBasalRateEntries = new ArrayList<>();
         List<TempBasalPercentEntry> tempBasalPercentEntries = new ArrayList<>();
         List<TempBasalCancelEntry> tempBasalCancelEntries = new ArrayList<>();
         List<NoteEntry> noteEntries = new ArrayList<>();
@@ -99,116 +105,166 @@ class NightScoutUpload {
         for (PumpStatusEvent record : records) {
 
             if (record.isValidSGV()) {
-                GlucoseEntry glucoseEntry = new GlucoseEntry();
-                glucoseEntry.setType("sgv");
-                glucoseEntry.setDirection(EntriesSerializer.getDirectionStringStatus(record.getCgmTrend()));
-                glucoseEntry.setDevice(record.getDeviceName());
-                glucoseEntry.setSgv(record.getSgv());
-                glucoseEntry.setDate(record.getCgmDate().getTime());
-                glucoseEntry.setDateString(record.getCgmDate().toString());
-                glucoseEntries.add(glucoseEntry);
+                SgvEntry sgvEntry = new SgvEntry();
+                sgvEntry.setType("sgv");
+                sgvEntry.setDirection(EntriesSerializer.getDirectionStringStatus(record.getCgmTrend()));
+                sgvEntry.setDevice(record.getDeviceName());
+                sgvEntry.setSgv(record.getSgv());
+                sgvEntry.setDate(record.getCgmDate().getTime());
+                sgvEntry.setDateString(record.getCgmDate().toString());
+                sgvEntries.add(sgvEntry);
             }
 
             if (record.isValidBGL()) {
-                BolusEntry bolusEntry = new BolusEntry();
-                bolusEntry.setType("mbg");
-                bolusEntry.setDate(record.getEventDate().getTime());
-                bolusEntry.setDateString(record.getEventDate().toString());
-                bolusEntry.setDevice(record.getDeviceName());
-                bolusEntry.setMbg(record.getRecentBGL());
-                bolusEntries.add(bolusEntry);
+
+                MbgEntry mbgEntry = new MbgEntry();
+                mbgEntry.setType("mbg");
+                mbgEntry.setDate(record.getEventDate().getTime());
+                mbgEntry.setDateString(record.getEventDate().toString());
+                mbgEntry.setDevice(record.getDeviceName());
+                mbgEntry.setMbg(record.getRecentBGL());
+                mbgEntries.add(mbgEntry);
+
+                // cgm offline or not in use (needed for NS to show bgl when no sgv data)
+                if (!record.isCgmActive() || record.isCgmWarmUp()) {
+                    ConfigurationStore configurationStore = ConfigurationStore.getInstance();
+                    BigDecimal bgl;
+                    String units;
+                    if (configurationStore.isMmolxl()) {
+                        bgl = new BigDecimal(record.getRecentBGL() / MMOLXLFACTOR).setScale(1, BigDecimal.ROUND_HALF_UP);
+                        units = "mmol";
+                    } else {
+                        bgl = new BigDecimal(record.getRecentBGL()).setScale(0);
+                        units = "mg/dl";
+                    }
+
+                    TreatmentEntry treatmentEntry = new TreatmentEntry();
+                    treatmentEntry.setCreatedAt(ISO8601_DATE_FORMAT.format(record.getEventDate()));
+                    treatmentEntry.setEventType("BG Check");
+                    treatmentEntry.setGlucoseType("Finger");
+                    treatmentEntry.setGlucose(bgl);
+                    treatmentEntry.setUnits(units);
+                    treatmentEntries.add(treatmentEntry);
+                }
             }
 
-            if (record.isValidBolus()) {
-                TreatmentEntry treatmentEntry = new TreatmentEntry();
-                treatmentEntry.setCreatedAt(ISO8601_DATE_FORMAT.format(record.getLastBolusDate()));
-                if (record.isValidBolusDual()) {
-                    treatmentEntry.setEventType("Bolus");
-                    treatmentEntry.setInsulin(record.getLastBolusAmount());
-                    treatmentEntry.setNotes("Dual bolus normal part delivered: " + record.getLastBolusAmount() + "u");
-
-                } else if (record.isValidBolusSquare()) {
-                    treatmentEntry.setEventType("Combo Bolus");
-                    treatmentEntry.setDuration(record.getLastBolusDuration());
-                    treatmentEntry.setSplitNow("0");
-                    treatmentEntry.setSplitExt("100");
-                    treatmentEntry.setRelative(2);
-                    treatmentEntry.setEnteredinsulin(String.valueOf(record.getLastBolusAmount()));
+            if (treatments) {
+
+                if (record.isValidBolus()) {
+
+                    if (record.isValidBolusDual()) {
+                        TreatmentEntry treatmentEntry = new TreatmentEntry();
+                        treatmentEntry.setCreatedAt(ISO8601_DATE_FORMAT.format(record.getLastBolusDate()));
+                        treatmentEntry.setEventType("Bolus");
+                        treatmentEntry.setInsulin(record.getLastBolusAmount());
+                        treatmentEntry.setNotes("Dual bolus normal part delivered: " + record.getLastBolusAmount() + "u");
+                        treatmentEntries.add(treatmentEntry);
+
+                    } else if (record.isValidBolusSquare()) {
+                        TreatmentEntry treatmentEntry = new TreatmentEntry();
+                        treatmentEntry.setCreatedAt(ISO8601_DATE_FORMAT.format(record.getLastBolusDate()));
+                        treatmentEntry.setEventType("Combo Bolus");
+                        treatmentEntry.setDuration(record.getLastBolusDuration());
+                        treatmentEntry.setSplitNow("0");
+                        treatmentEntry.setSplitExt("100");
+                        treatmentEntry.setRelative(2);
+                        treatmentEntry.setEnteredinsulin(String.valueOf(record.getLastBolusAmount()));
+                        treatmentEntries.add(treatmentEntry);
+
+                        noteEntries.add(new NoteEntry(
+                                "Announcement",
+                                ISO8601_DATE_FORMAT.format(record.getLastBolusDate().getTime() + (record.getLastBolusDuration() * 60 * 1000)),
+                                "Square bolus delivered: " + record.getLastBolusAmount() + "u Duration: " + record.getLastBolusDuration() + " minutes"
+                        ));
+
+                    } else {
+                        TreatmentEntry treatmentEntry = new TreatmentEntry();
+                        treatmentEntry.setCreatedAt(ISO8601_DATE_FORMAT.format(record.getLastBolusDate()));
+                        treatmentEntry.setEventType("Bolus");
+                        treatmentEntry.setInsulin(record.getLastBolusAmount());
+                        treatmentEntries.add(treatmentEntry);
+                    }
+                }
 
-                    noteEntries.add(new NoteEntry(
-                            "Announcement",
-                            ISO8601_DATE_FORMAT.format(record.getLastBolusDate().getTime() + (record.getLastBolusDuration() * 60 * 1000)),
-                            "Square bolus delivered: " + record.getLastBolusAmount() + "u Duration: " + record.getLastBolusDuration() + " minutes"
-                    ));
-                } else {
-                    treatmentEntry.setEventType("Bolus");
-                    treatmentEntry.setInsulin(record.getLastBolusAmount());
+                if (record.isValidTEMPBASAL()) {
+                    if (record.getTempBasalMinutesRemaining() > 0 && record.getTempBasalPercentage() > 0) {
+                        tempBasalPercentEntries.add(new TempBasalPercentEntry(
+                                ISO8601_DATE_FORMAT.format(record.getEventDate()),
+                                "Temp Basal started approx: " + NOTE_DATE_FORMAT.format(record.getTempBasalAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getTempBasalBeforeDate()),
+                                record.getTempBasalMinutesRemaining(),
+                                record.getTempBasalPercentage() - 100
+                        ));
+                    } else if (record.getTempBasalMinutesRemaining() > 0) {
+                        tempBasalRateEntries.add(new TempBasalRateEntry(
+                                ISO8601_DATE_FORMAT.format(record.getEventDate()),
+                                "Temp Basal started approx: " + NOTE_DATE_FORMAT.format(record.getTempBasalAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getTempBasalBeforeDate()),
+                                record.getTempBasalMinutesRemaining(),
+                                record.getTempBasalRate()
+                        ));
+                    } else {
+                        tempBasalCancelEntries.add(new TempBasalCancelEntry(
+                                ISO8601_DATE_FORMAT.format(record.getEventDate()),
+                                "Temp Basal stopped approx: " + NOTE_DATE_FORMAT.format(record.getTempBasalAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getTempBasalBeforeDate())
+                        ));
+                    }
                 }
-                treatmentEntries.add(treatmentEntry);
-            }
 
-            if (record.isValidTEMPBASAL()) {
-                if (record.getTempBasalMinutesRemaining() > 0 && record.getTempBasalPercentage() > 0) {
-                    tempBasalPercentEntries.add(new TempBasalPercentEntry(
-                            ISO8601_DATE_FORMAT.format(record.getEventDate()),
-                            "Temp Basal started approx: " + NOTE_DATE_FORMAT.format(record.getTempBasalAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getEventDate()),
-                            record.getTempBasalMinutesRemaining(),
-                            record.getTempBasalPercentage() - 100
-                    ));
-                } else if (record.getTempBasalMinutesRemaining() > 0) {
-                    tempBasalAbsoluteEntries.add(new TempBasalAbsoluteEntry(
+                if (record.isValidSUSPEND()) {
+                    tempBasalRateEntries.add(new TempBasalRateEntry(
                             ISO8601_DATE_FORMAT.format(record.getEventDate()),
-                            "Temp Basal started approx: " + NOTE_DATE_FORMAT.format(record.getTempBasalAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getEventDate()),
-                            record.getTempBasalMinutesRemaining(),
-                            record.getTempBasalRate()
+                            "Pump suspended insulin delivery approx: " + NOTE_DATE_FORMAT.format(record.getSuspendAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getSuspendBeforeDate()),
+                            60,
+                            0
                     ));
-                } else {
+                }
+                if (record.isValidSUSPENDOFF()) {
                     tempBasalCancelEntries.add(new TempBasalCancelEntry(
                             ISO8601_DATE_FORMAT.format(record.getEventDate()),
-                            "Temp Basal stopped approx: " + NOTE_DATE_FORMAT.format(record.getTempBasalAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getEventDate())
+                            "Pump resumed insulin delivery approx: " + NOTE_DATE_FORMAT.format(record.getSuspendAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getSuspendBeforeDate())
+                    ));
+                }
+
+                if (record.isValidSAGE()) {
+                    noteEntries.add(new NoteEntry(
+                            "Sensor Start",
+                            ISO8601_DATE_FORMAT.format(record.getSageAfterDate().getTime() - (record.getSageAfterDate().getTime() - record.getSageBeforeDate().getTime()) / 2),
+                            "Sensor changed approx: " + NOTE_DATE_FORMAT.format(record.getSageAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getSageBeforeDate())
+                    ));
+                }
+                if (record.isValidCAGE()) {
+                    noteEntries.add(new NoteEntry(
+                            "Site Change",
+                            ISO8601_DATE_FORMAT.format(record.getCageAfterDate().getTime() - (record.getCageAfterDate().getTime() - record.getCageBeforeDate().getTime()) / 2),
+                            "Reservoir changed approx: " + NOTE_DATE_FORMAT.format(record.getCageAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getCageBeforeDate())
+                    ));
+                }
+                if (record.isValidBATTERY()) {
+                    noteEntries.add(new NoteEntry(
+                            "Note",
+                            ISO8601_DATE_FORMAT.format(record.getBatteryAfterDate().getTime() - (record.getBatteryAfterDate().getTime() - record.getBatteryBeforeDate().getTime()) / 2),
+                            "Pump battery changed approx: " + NOTE_DATE_FORMAT.format(record.getBatteryAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getBatteryBeforeDate())
                     ));
                 }
-            }
 
-            if (record.isValidSAGE()) {
-                noteEntries.add(new NoteEntry(
-                        "Sensor Start",
-                        ISO8601_DATE_FORMAT.format(record.getSageAfterDate().getTime() - (record.getSageAfterDate().getTime() - record.getSageBeforeDate().getTime()) / 2),
-                        "Sensor changed approx: " + NOTE_DATE_FORMAT.format(record.getSageAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getSageBeforeDate())
-                ));
-            }
-            if (record.isValidCAGE()) {
-                noteEntries.add(new NoteEntry(
-                        "Site Change",
-                        ISO8601_DATE_FORMAT.format(record.getCageAfterDate().getTime() - (record.getCageAfterDate().getTime() - record.getCageBeforeDate().getTime()) / 2),
-                        "Reservoir changed approx: " + NOTE_DATE_FORMAT.format(record.getCageAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getCageBeforeDate())
-                ));
-            }
-            if (record.isValidBATTERY()) {
-                noteEntries.add(new NoteEntry(
-                        "Note",
-                        ISO8601_DATE_FORMAT.format(record.getBatteryAfterDate().getTime() - (record.getBatteryAfterDate().getTime() - record.getBatteryBeforeDate().getTime()) / 2),
-                        "Pump battery changed approx: " + NOTE_DATE_FORMAT.format(record.getBatteryAfterDate()) + " - " + NOTE_DATE_FORMAT.format(record.getBatteryBeforeDate())
-                ));
             }
 
         }
 
         boolean uploaded = true;
-        if (glucoseEntries.size() > 0) {
-            Response<ResponseBody> result = glucoseEndpoints.sendEntries(glucoseEntries).execute();
+        if (sgvEntries.size() > 0) {
+            Response<ResponseBody> result = sgvEndpoints.sendEntries(sgvEntries).execute();
             uploaded = result.isSuccessful();
         }
-        if (bolusEntries.size() > 0) {
-            Response<ResponseBody> result = bolusEndpoints.sendEntries(bolusEntries).execute();
+        if (mbgEntries.size() > 0) {
+            Response<ResponseBody> result = mbgEndpoints.sendEntries(mbgEntries).execute();
             uploaded = uploaded && result.isSuccessful();
         }
         if (treatmentEntries.size() > 0) {
             Response<ResponseBody> result = treatmentEndpoints.sendEntries(treatmentEntries).execute();
             uploaded = uploaded && result.isSuccessful();
         }
-        if (tempBasalAbsoluteEntries.size() > 0) {
-            Response<ResponseBody> result = tempBasalAbsoluteEndpoints.sendEntries(tempBasalAbsoluteEntries).execute();
+        if (tempBasalRateEntries.size() > 0) {
+            Response<ResponseBody> result = tempBasalRateEndpoints.sendEntries(tempBasalRateEntries).execute();
             uploaded = uploaded && result.isSuccessful();
         }
         if (tempBasalPercentEntries.size() > 0) {
@@ -238,52 +294,81 @@ class NightScoutUpload {
             Battery battery = new Battery(record.getBatteryPercentage());
             PumpStatus pumpstatus;
 
+            // shorten pump status when needed to accommodate mobile browsers
+            boolean shorten = false;
+            if ((record.isBolusingSquare() || record.isBolusingDual()) && record.isTempBasalActive())
+                shorten = true;
+
             String statusPUMP = "normal";
-            if (record.isBolusingNormal())
+            if (record.isBolusingNormal()) {
                 statusPUMP = "bolusing";
-            else if (record.isBolusingSquare())
-                statusPUMP = "square>>" + record.getBolusingDelivered() + "u-" + (record.getBolusingMinutesRemaining() >= 60 ? record.getBolusingMinutesRemaining() / 60 + "h" : "") + record.getBolusingMinutesRemaining() % 60 + "m";
-            else if (record.isBolusingDual())
-                statusPUMP = "dual>>" + record.getBolusingDelivered() + "u-" + (record.getBolusingMinutesRemaining() >= 60 ? record.getBolusingMinutesRemaining() / 60 + "h" : "") + record.getBolusingMinutesRemaining() % 60 + "m";
-            else if (record.isSuspended())
+            } else if (record.isSuspended()) {
                 statusPUMP = "suspended";
-            else if (record.getTempBasalMinutesRemaining() > 0 & record.getTempBasalPercentage() != 0)
-                statusPUMP = "temp>>" + record.getTempBasalPercentage() + "%-" + (record.getTempBasalMinutesRemaining() >= 60 ? record.getTempBasalMinutesRemaining() / 60 + "h" : "") + record.getTempBasalMinutesRemaining() % 60 + "m";
-            else if (record.getTempBasalMinutesRemaining() > 0)
-                statusPUMP = "temp>>" + record.getTempBasalRate() + "u-" + (record.getTempBasalMinutesRemaining() >= 60 ? record.getTempBasalMinutesRemaining() / 60 + "h" : "") + record.getTempBasalMinutesRemaining() % 60 + "m";
+            } else {
+                if (record.isBolusingSquare()) {
+                    if (shorten)
+                        statusPUMP = "S>" + record.getBolusingDelivered() + "u-" + record.getBolusingMinutesRemaining() + "m";
+                    else
+                        statusPUMP = "square>>" + record.getBolusingDelivered() + "u-" + (record.getBolusingMinutesRemaining() >= 60 ? record.getBolusingMinutesRemaining() / 60 + "h" : "") + record.getBolusingMinutesRemaining() % 60 + "m";
+                    shorten = true;
+                } else if (record.isBolusingDual()) {
+                    if (shorten)
+                        statusPUMP = "D>" + record.getBolusingDelivered() + "-" + record.getBolusingMinutesRemaining() + "m";
+                    else
+                        statusPUMP = "dual>>" + record.getBolusingDelivered() + "u-" + (record.getBolusingMinutesRemaining() >= 60 ? record.getBolusingMinutesRemaining() / 60 + "h" : "") + record.getBolusingMinutesRemaining() % 60 + "m";
+                    shorten = true;
+                }
+                if (record.getTempBasalMinutesRemaining() > 0 & record.getTempBasalPercentage() != 0) {
+                    if (shorten)
+                        statusPUMP = " T>" + record.getTempBasalPercentage() + "%-" + record.getTempBasalMinutesRemaining() + "m";
+                    else
+                        statusPUMP = "temp>>" + record.getTempBasalPercentage() + "%-" + (record.getTempBasalMinutesRemaining() >= 60 ? record.getTempBasalMinutesRemaining() / 60 + "h" : "") + record.getTempBasalMinutesRemaining() % 60 + "m";
+                    shorten = true;
+                } else if (record.getTempBasalMinutesRemaining() > 0) {
+                    if (shorten)
+                        statusPUMP = " T>" + record.getTempBasalRate() + "-" + record.getTempBasalMinutesRemaining() + "m";
+                    else
+                        statusPUMP = "temp>>" + record.getTempBasalRate() + "u-" + (record.getTempBasalMinutesRemaining() >= 60 ? record.getTempBasalMinutesRemaining() / 60 + "h" : "") + record.getTempBasalMinutesRemaining() % 60 + "m";
+                    shorten = true;
+                }
+            }
+
             if (record.getAlert() > 0)
                 statusPUMP = "⚠ " + statusPUMP;
 
             String statusCGM = "";
-            String statusCGMbattery = "";
             if (record.isCgmActive()) {
                 if (record.getTransmitterBattery() > 80)
-                    statusCGMbattery = "::::";
+                    statusCGM = shorten ? "" : ":::: ";
                 else if (record.getTransmitterBattery() > 55)
-                    statusCGMbattery = ":::.";
+                    statusCGM = shorten ? "" : ":::. ";
                 else if (record.getTransmitterBattery() > 30)
-                    statusCGMbattery = "::..";
+                    statusCGM = shorten ? "" : "::.. ";
                 else if (record.getTransmitterBattery() > 10)
-                    statusCGMbattery = ":...";
+                    statusCGM = shorten ? "" : ":... ";
                 else
-                    statusCGMbattery = "....";
+                    statusCGM = shorten ? "" : ".... ";
                 if (record.isCgmCalibrating())
-                    statusCGM += " calibrating";
+                    statusCGM += shorten ? "cal" : "calibrating";
                 else if (record.isCgmCalibrationComplete())
-                    statusCGM += " cal.complete";
+                    statusCGM += shorten ? "cal" : "cal.complete";
                 else {
                     if (record.isCgmWarmUp())
-                        statusCGM += "warmup ";
-                    if (record.getCalibrationDueMinutes() > 0)
-                        statusCGM += (record.getCalibrationDueMinutes() >= 60 ? record.getCalibrationDueMinutes() / 60 + "h" : "") + record.getCalibrationDueMinutes() % 60 + "m";
+                        statusCGM += shorten ? "WU" : "warmup ";
+                    if (record.getCalibrationDueMinutes() > 0) {
+                        if (shorten)
+                            statusCGM += (record.getCalibrationDueMinutes() >= 120 ? record.getCalibrationDueMinutes() / 60 + "h" : record.getCalibrationDueMinutes() + "m");
+                        else
+                            statusCGM += (record.getCalibrationDueMinutes() >= 60 ? record.getCalibrationDueMinutes() / 60 + "h" : "") + record.getCalibrationDueMinutes() % 60 + "m";
+                    }
                     else
-                        statusCGM += "calibrate now!";
+                        statusCGM += shorten ? "cal.now" : "calibrate now!";
                 }
             } else {
-                statusCGM+= "cgm n/a";
+                statusCGM += shorten ? "n/a" : "cgm n/a";
             }
 
-            pumpstatus = new PumpStatus(false, false, statusPUMP + " " +  statusCGMbattery + " " + statusCGM);
+            pumpstatus = new PumpStatus(false, false, statusPUMP + " " + statusCGM);
 
             PumpInfo pumpInfo = new PumpInfo(
                     ISO8601_DATE_FORMAT.format(record.getEventDate()),
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
index e191ecd0fbb5350a9eae61291998000884bb6562..30dcd7cdc73e1c3bddebe863d3af2c5201ade573 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
@@ -60,6 +60,8 @@ public class NightscoutUploadIntentService extends IntentService {
             SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
 
             Boolean enableRESTUpload = prefs.getBoolean("EnableRESTUpload", false);
+            Boolean enableTreatmentsUpload = prefs.getBoolean("EnableTreatmentsUpload", false);
+
             try {
                 if (enableRESTUpload) {
                     long start = System.currentTimeMillis();
@@ -67,7 +69,7 @@ public class NightscoutUploadIntentService extends IntentService {
                     String urlSetting = prefs.getString(mContext.getString(R.string.preference_nightscout_url), "");
                     String secretSetting = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET");
                     Boolean uploadSuccess = mNightScoutUpload.doRESTUpload(urlSetting,
-                            secretSetting, DataStore.getInstance().getUploaderBatteryLevel(), records);
+                            secretSetting, enableTreatmentsUpload, DataStore.getInstance().getUploaderBatteryLevel(), records);
                     if (uploadSuccess) {
                         mRealm.beginTransaction();
                         for (PumpStatusEvent updateRecord : records) {
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 e9a4e0339078630b4593e57f2c1bf0f22497903d..c6f24d69bfb4a71d813d6e54400edc5e92f9277a 100644
--- a/app/src/main/java/info/nightscout/android/utils/DataStore.java
+++ b/app/src/main/java/info/nightscout/android/utils/DataStore.java
@@ -1,6 +1,8 @@
 package info.nightscout.android.utils;
 
 
+import java.util.Date;
+
 /**
  * Created by volker on 30.03.2017.
  */
@@ -8,8 +10,11 @@ package info.nightscout.android.utils;
 public class DataStore {
     private static DataStore instance;
 
+    private Date uploaderStartDate;
+
     private long activePumpMac = 0;
     private int uploaderBatteryLevel = 0;
+
     private int pumpCgmNA = 0;
 
     private int CommsSuccess = 0;
@@ -19,6 +24,7 @@ public class DataStore {
     private int CommsSgvSuccess = 0;
     private int PumpLostSensorError = 0;
     private int PumpClockError = 0;
+    private int PumpBatteryError = 0;
 
     private DataStore() {}
 
@@ -26,10 +32,15 @@ public class DataStore {
         if (DataStore.instance == null) {
             instance = new DataStore();
 
+            instance.uploaderStartDate = new Date();
         }
         return instance;
     }
 
+    public Date getUploaderStartDate() {
+        return uploaderStartDate;
+    }
+
     public long getActivePumpMac() {
         return activePumpMac;
     }
@@ -132,6 +143,16 @@ public class DataStore {
         this.PumpClockError = 0;
     }
 
+    public int getPumpBatteryError() {
+        return PumpBatteryError;
+    }
+
+    public int incPumpBatteryError() { return PumpBatteryError++; }
+
+    public void clearPumpBatteryError() {
+        this.PumpBatteryError = 0;
+    }
+
     public void clearAllCommsErrors() {
         this.CommsSuccess = 0;
         this.CommsError = 0;
@@ -139,5 +160,6 @@ public class DataStore {
         this.CommsSignalError = 0;
         this.PumpLostSensorError = 0;
         this.PumpClockError = 0;
+        this.PumpBatteryError = 0;
     }
 }
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 e8f056ed7e9845d3a3d9ec9ef6f494a2575587aa..22be13663c6931536562a3aa7ecb7ee20c4c4089 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
@@ -53,7 +53,6 @@ public class XDripPlusUploadIntentService extends IntentService {
         Log.i(TAG, "onCreate called");
         mContext = this.getBaseContext();
     }
-// check this stuff!!! pogman!
 
     @Override
     protected void onHandleIntent(Intent intent) {
@@ -62,8 +61,9 @@ public class XDripPlusUploadIntentService extends IntentService {
 
         RealmResults<PumpStatusEvent> all_records = mRealm
                 .where(PumpStatusEvent.class)
-                .notEqualTo("validSGV", false)
-//                .notEqualTo("sgv", 0)
+                .equalTo("validSGV", true)
+                .or()
+                .equalTo("validBGL", true)
                 .findAllSorted("eventDate", Sort.DESCENDING);
 
         // get the most recent record and send that
@@ -141,20 +141,22 @@ public class XDripPlusUploadIntentService extends IntentService {
     }
 
     private void addSgvEntry(JSONArray entriesArray, PumpStatusEvent pumpRecord) throws Exception {
-        JSONObject json = new JSONObject();
-        // TODO replace with Retrofit/EntriesSerializer
-        json.put("sgv", pumpRecord.getSgv());
-        json.put("direction", EntriesSerializer.getDirectionString(pumpRecord.getCgmTrend()));
-        json.put("device", pumpRecord.getDeviceName());
-        json.put("type", "sgv");
-        json.put("date", pumpRecord.getCgmDate().getTime());
-        json.put("dateString", pumpRecord.getCgmDate());
-
-        entriesArray.put(json);
+        if (pumpRecord.isValidSGV()) {
+            JSONObject json = new JSONObject();
+            // TODO replace with Retrofit/EntriesSerializer
+            json.put("sgv", pumpRecord.getSgv());
+            json.put("direction", EntriesSerializer.getDirectionString(pumpRecord.getCgmTrend()));
+            json.put("device", pumpRecord.getDeviceName());
+            json.put("type", "sgv");
+            json.put("date", pumpRecord.getCgmDate().getTime());
+            json.put("dateString", pumpRecord.getCgmDate());
+
+            entriesArray.put(json);
+        }
     }
 
     private void addMbgEntry(JSONArray entriesArray, PumpStatusEvent pumpRecord) throws Exception {
-        if (pumpRecord.hasRecentBolusWizard()) {
+        if (pumpRecord.isValidBGL()) {
             JSONObject json = new JSONObject();
 
             // TODO replace with Retrofit/EntriesSerializer
diff --git a/app/src/main/java/info/nightscout/api/BolusEndpoints.java b/app/src/main/java/info/nightscout/api/MbgEndpoints.java
similarity index 63%
rename from app/src/main/java/info/nightscout/api/BolusEndpoints.java
rename to app/src/main/java/info/nightscout/api/MbgEndpoints.java
index a1c2a56e35eacaa534b5e5ede7de4fca577672c8..9c443342275e0b708b7beaef4c8c489375483479 100644
--- a/app/src/main/java/info/nightscout/api/BolusEndpoints.java
+++ b/app/src/main/java/info/nightscout/api/MbgEndpoints.java
@@ -8,57 +8,36 @@ import retrofit2.http.Body;
 import retrofit2.http.Headers;
 import retrofit2.http.POST;
 
-public interface BolusEndpoints {
+public interface MbgEndpoints {
 
-    class BolusEntry {
+    class MbgEntry {
         String type;
         String dateString;
         long date;
         int mbg;
         String device;
 
-        public BolusEntry() {  }
-
-        public String getType() {
-            return type;
-        }
+        public MbgEntry() {  }
 
         public void setType(String type) {
             this.type = type;
         }
 
-        public String getDateString() {
-            return dateString;
-        }
-
         public void setDateString(String dateString) {
             this.dateString = dateString;
         }
 
-        public long getDate() {
-            return date;
-        }
-
         public void setDate(long date) {
             this.date = date;
         }
 
-        public int getMbg() {
-            return mbg;
-        }
-
         public void setMbg(int mbg) {
             this.mbg = mbg;
         }
 
-        public String getDevice() {
-            return device;
-        }
-
         public void setDevice(String device) {
             this.device = device;
         }
-
     }
 
     @Headers({
@@ -66,8 +45,7 @@ public interface BolusEndpoints {
             "Content-type: application/json"
     })
     @POST("/api/v1/entries")
-    Call<ResponseBody> sendEntries(@Body List<BolusEntry> entries);
-
+    Call<ResponseBody> sendEntries(@Body List<MbgEntry> entries);
 }
 
 
diff --git a/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java b/app/src/main/java/info/nightscout/api/SgvEndpoints.java
similarity index 62%
rename from app/src/main/java/info/nightscout/api/GlucoseEndpoints.java
rename to app/src/main/java/info/nightscout/api/SgvEndpoints.java
index d34c5e7abdae5efadc346bc560eb54aee252dacb..96dd7bb376d5e73ad325bea640d134ab66144ce5 100644
--- a/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java
+++ b/app/src/main/java/info/nightscout/api/SgvEndpoints.java
@@ -8,10 +8,9 @@ import retrofit2.http.Body;
 import retrofit2.http.Headers;
 import retrofit2.http.POST;
 
-public interface GlucoseEndpoints {
-
-    class GlucoseEntry {
+public interface SgvEndpoints {
 
+    class SgvEntry {
         String type;
         String dateString;
         long date;
@@ -19,55 +18,31 @@ public interface GlucoseEndpoints {
         String direction;
         String device;
 
-        public String getType() {
-            return type;
-        }
-
         public void setType(String type) {
             this.type = type;
         }
 
-        public String getDateString() {
-            return dateString;
-        }
-
         public void setDateString(String dateString) {
             this.dateString = dateString;
         }
 
-        public long getDate() {
-            return date;
-        }
-
         public void setDate(long date) {
             this.date = date;
         }
 
-        public int getSgv() {
-            return sgv;
-        }
-
         public void setSgv(int sgv) {
             this.sgv = sgv;
         }
 
-        public String getDirection() {
-            return direction;
-        }
-
         public void setDirection(String direction) {
             this.direction = direction;
         }
 
-        public String getDevice() {
-            return device;
-        }
-
         public void setDevice(String device) {
             this.device = device;
         }
 
-        public GlucoseEntry() {  }
+        public SgvEntry() {  }
     }
 
     @Headers({
@@ -75,8 +50,7 @@ public interface GlucoseEndpoints {
             "Content-type: application/json"
     })
     @POST("/api/v1/entries")
-    Call<ResponseBody> sendEntries(@Body List<GlucoseEntry> entries);
-
+    Call<ResponseBody> sendEntries(@Body List<SgvEntry> entries);
 }
 
 
diff --git a/app/src/main/java/info/nightscout/api/TempBasalAbsoluteEndpoints.java b/app/src/main/java/info/nightscout/api/TempBasalRateEndpoints.java
similarity index 70%
rename from app/src/main/java/info/nightscout/api/TempBasalAbsoluteEndpoints.java
rename to app/src/main/java/info/nightscout/api/TempBasalRateEndpoints.java
index d393223194a5fe2cd348e0121e9998d243387216..27f7d4ff9fbd7e91d4502ead0e14ebe93e494d5b 100644
--- a/app/src/main/java/info/nightscout/api/TempBasalAbsoluteEndpoints.java
+++ b/app/src/main/java/info/nightscout/api/TempBasalRateEndpoints.java
@@ -8,16 +8,16 @@ import retrofit2.http.Body;
 import retrofit2.http.Headers;
 import retrofit2.http.POST;
 
-public interface TempBasalAbsoluteEndpoints {
+public interface TempBasalRateEndpoints {
 
-    class TempBasalAbsoluteEntry {
+    class TempBasalRateEntry {
         String eventType = "Temp Basal";
         String created_at;
         String notes;
         float duration;
         float absolute;
 
-        public TempBasalAbsoluteEntry(String created_at, String notes, float duration, float absolute) {
+        public TempBasalRateEntry(String created_at, String notes, float duration, float absolute) {
             this.created_at = created_at;
             this.notes = notes;
             this.duration = duration;
@@ -30,5 +30,5 @@ public interface TempBasalAbsoluteEndpoints {
             "Content-type: application/json"
     })
     @POST("/api/v1/treatments")
-    Call<ResponseBody> sendEntries(@Body List<TempBasalAbsoluteEntry> entries);
+    Call<ResponseBody> sendEntries(@Body List<TempBasalRateEntry> entries);
 }
diff --git a/app/src/main/java/info/nightscout/api/TreatmentEndpoints.java b/app/src/main/java/info/nightscout/api/TreatmentEndpoints.java
index 0ebb1b43325bb94bcd573e283f905587f04811bc..129af210241ddda4230f8401b41647a9ed4d69bf 100644
--- a/app/src/main/java/info/nightscout/api/TreatmentEndpoints.java
+++ b/app/src/main/java/info/nightscout/api/TreatmentEndpoints.java
@@ -1,7 +1,6 @@
 package info.nightscout.api;
 
-import android.support.annotation.Nullable;
-
+import java.math.BigDecimal;
 import java.util.List;
 
 import okhttp3.ResponseBody;
@@ -18,92 +17,66 @@ public interface TreatmentEndpoints {
         String enteredinsulin;
         String splitNow;
         String splitExt;
+        String units;
+        String glucoseType;
         String notes;
         String device;
         float insulin;
         float duration;
         float relative;
-
-        public String getEventType() {
-            return eventType;
-        }
+        BigDecimal glucose;
 
         public void setEventType(String eventType) {
             this.eventType = eventType;
         }
 
-        public String getCreatedAt() {
-            return created_at;
-        }
-
         public void setCreatedAt(String created_at) {
             this.created_at = created_at;
         }
 
-        public String getDevice() {
-            return device;
-        }
-
         public void setDevice(String device) {
             this.device = device;
         }
 
-        public float getInsulin() {
-            return insulin;
-        }
-
         public void setInsulin(float insulin) {
             this.insulin = insulin;
         }
 
-        public float getDuration() {
-            return duration;
+        public void setGlucose(BigDecimal glucose) {
+            this.glucose = glucose;
         }
 
         public void setDuration(float duration) {
             this.duration = duration;
         }
 
-        public float getRelative() {
-            return relative;
-        }
-
         public void setRelative(float relative) {
             this.relative = relative;
         }
 
-        public String getEnteredinsulin() {
-            return enteredinsulin;
-        }
-
         public void setEnteredinsulin(String enteredinsulin) {
             this.enteredinsulin = enteredinsulin;
         }
 
-        public String getSplitNow() {
-            return splitNow;
-        }
-
         public void setSplitNow(String splitNow) {
             this.splitNow = splitNow;
         }
 
-        public String getSplitExt() {
-            return splitExt;
-        }
-
         public void setSplitExt(String splitExt) {
             this.splitExt = splitExt;
         }
 
-        public String getNotes() {
-            return notes;
+        public void setUnits(String units) {
+            this.units = units;
+        }
+
+        public void setGlucoseType(String glucoseType) {
+            this.glucoseType = glucoseType;
         }
 
         public void setNotes(String notes) {
             this.notes = notes;
         }
-
     }
 
     @Headers({
diff --git a/app/src/main/java/info/nightscout/api/UploadApi.java b/app/src/main/java/info/nightscout/api/UploadApi.java
index 05e2520576e3b55474874d928bc883558b4634dc..70ce741c202ab545cbbd805b2fa429dab1887551 100644
--- a/app/src/main/java/info/nightscout/api/UploadApi.java
+++ b/app/src/main/java/info/nightscout/api/UploadApi.java
@@ -14,20 +14,20 @@ import retrofit2.converter.gson.GsonConverterFactory;
 
 public class UploadApi {
     private Retrofit retrofit;
-    private GlucoseEndpoints glucoseEndpoints;
-    private BolusEndpoints bolusEndpoints;
+    private SgvEndpoints sgvEndpoints;
+    private MbgEndpoints mbgEndpoints;
     private DeviceEndpoints deviceEndpoints;
     private TreatmentEndpoints treatmentEndpoints;
-    private TempBasalAbsoluteEndpoints tempBasalAbsoluteEndpoints;
+    private TempBasalRateEndpoints tempBasalRateEndpoints;
     private TempBasalPercentEndpoints tempBasalPercentEndpoints;
     private TempBasalCancelEndpoints tempBasalCancelEndpoints;
     private NoteEndpoints noteEndpoints;
 
-    public GlucoseEndpoints getGlucoseEndpoints() {
-        return glucoseEndpoints;
+    public SgvEndpoints getSgvEndpoints() {
+        return sgvEndpoints;
     }
-    public BolusEndpoints getBolusEndpoints() {
-        return bolusEndpoints;
+    public MbgEndpoints getMbgEndpoints() {
+        return mbgEndpoints;
     }
     public DeviceEndpoints getDeviceEndpoints() {
         return deviceEndpoints;
@@ -35,8 +35,8 @@ public class UploadApi {
     public TreatmentEndpoints getTreatmentEndpoints() {
         return treatmentEndpoints;
     }
-    public TempBasalAbsoluteEndpoints getTempBasalAbsoluteEndpoints() {
-        return tempBasalAbsoluteEndpoints;
+    public TempBasalRateEndpoints getTempBasalRateEndpoints() {
+        return tempBasalRateEndpoints;
     }
     public TempBasalPercentEndpoints getTempBasalPercentEndpoints() {
         return tempBasalPercentEndpoints;
@@ -88,11 +88,11 @@ public class UploadApi {
                 .addConverterFactory(GsonConverterFactory.create())
                 .build();
 
-        glucoseEndpoints = retrofit.create(GlucoseEndpoints.class);
-        bolusEndpoints = retrofit.create(BolusEndpoints.class);
+        sgvEndpoints = retrofit.create(SgvEndpoints.class);
+        mbgEndpoints = retrofit.create(MbgEndpoints.class);
         deviceEndpoints = retrofit.create(DeviceEndpoints.class);
         treatmentEndpoints = retrofit.create(TreatmentEndpoints.class);
-        tempBasalAbsoluteEndpoints = retrofit.create(TempBasalAbsoluteEndpoints.class);
+        tempBasalRateEndpoints = retrofit.create(TempBasalRateEndpoints.class);
         tempBasalPercentEndpoints = retrofit.create(TempBasalPercentEndpoints.class);
         tempBasalCancelEndpoints = retrofit.create(TempBasalCancelEndpoints.class);
         noteEndpoints = retrofit.create(NoteEndpoints.class);
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index ff89a6f2bb0e9027c0f4fc857a79595b7a6fe4d5..d590b78082d9dcf96ba6f0d30679d45121be3e77 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -19,12 +19,12 @@
             android:switchTextOn="2"
             android:title="Decimals"/>
         <ListPreference
-            android:key="pollInterval"
             android:defaultValue="300000"
-            android:title="@string/preferences_poll_interval"
-            android:summary="%s"
             android:entries="@array/poll_interval"
-            android:entryValues="@array/poll_interval_millis"/>
+            android:entryValues="@array/poll_interval_millis"
+            android:key="pollInterval"
+            android:summary="%s"
+            android:title="@string/preferences_poll_interval" />
         <info.nightscout.android.utils.CustomSwitchPreference
             android:disableDependentsState="false"
             android:key="doublePollOnPumpAway"
@@ -70,6 +70,10 @@
             android:dialogTitle="Enter your Nightscout API secret"
             android:key="@string/preference_api_secret"
             android:title="API Secret"/>
+        <CheckBoxPreference android:title="Treatments"
+            android:key="EnableTreatmentsUpload"
+            android:dependency="@string/preference_enable_rest_upload"
+            android:summary="Enable upload of treatments to Nightscout"/>
         <Preference android:title="scan NS-Autoconfig QR-Code"
             android:key="scanButton"
             android:dependency="@string/preference_enable_rest_upload"