diff --git a/app/build.gradle b/app/build.gradle
index 321863d615cb36775b630d58e4edd1721a5f7a06..2d2734cdf908f6db8dfc2d17acdc0a24663db37f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,7 +7,7 @@ buildscript {
 
     dependencies {
         classpath 'io.fabric.tools:gradle:1.21.6'
-        classpath 'io.realm:realm-gradle-plugin:1.1.1'
+        classpath 'io.realm:realm-gradle-plugin:2.3.1'
         classpath 'org.ajoberstar:grgit:1.5.0'
     }
 }
@@ -161,4 +161,13 @@ dependencies {
     compile 'com.google.code.gson:gson:2.7'
     compile 'com.squareup.retrofit2:retrofit:2.1.0'
     compile 'com.squareup.retrofit2:converter-gson:2.1.0'
+    compile 'com.squareup.okhttp3:okhttp:3.3.1'
+    compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
+    testCompile 'junit:junit:4.12'
+    testCompile 'org.powermock:powermock:1.6.5'
+    testCompile 'org.powermock:powermock-module-junit4:1.6.5'
+    testCompile 'org.powermock:powermock-api-mockito:1.6.5'
+    testCompile 'org.json:json:20140107'
+
+
 }
\ No newline at end of file
diff --git a/app/gradle.properties b/app/gradle.properties
index 1dd0e26d2b59d84aa9b32ab72e3c5b99065efabe..c2066d43f1cea3abc965486bf1b3ce582535dfc0 100644
--- a/app/gradle.properties
+++ b/app/gradle.properties
@@ -1 +1,2 @@
-version=0.5.0-SNAPSHOT
+#version=0.5.0-SNAPSHOT
+version=0.5.1-SNAPSHOT
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 80e56888d3b01828035953934ed4cb6cb4d761ef..1aae2ae9be366f96f9bef939cce177454d503f14 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -88,7 +88,7 @@
         <receiver android:name=".medtronic.service.MedtronicCnlAlarmReceiver"></receiver>
         <meta-data
             android:name="io.fabric.ApiKey"
-            android:value="aa26e770bd4f7480eed7cabb63a84363ecd12009" />
+            android:value="YOUR_FABRIC_KEY" />
     </application>
 
 </manifest>
\ No newline at end of file
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 b958a2c3ac004079815a46121313dc9e74cf097a..b58190a910fc975082a7fd085d04d592d0a0aaf2 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
@@ -286,7 +286,7 @@ public class MedtronicCnlIntentService extends IntentService {
             MedtronicCnlAlarmReceiver.completeWakefulIntent(intent);
         }
     }
-
+    
     // reliable wake alarm manager wake up for all android versions
     public static void wakeUpIntent(Context context, long wakeTime, PendingIntent pendingIntent) {
         final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
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 ab95d50f6d346d506d3a6f03a992e53cfaa00804..d1f1f3ffc08b31c04357b90567a3b794869f59c7 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
@@ -81,6 +81,10 @@ public class PumpStatusEvent extends RealmObject {
         return CGM_TREND.valueOf(cgmTrend);
     }
 
+    public String getCgmTrendString() {
+        return cgmTrend;
+    }
+
     public void setCgmTrend(CGM_TREND cgmTrend) {
         this.cgmTrend = cgmTrend.name();
     }
diff --git a/app/src/main/java/info/nightscout/android/model/medtronicNg/StatusEvent.java b/app/src/main/java/info/nightscout/android/model/medtronicNg/StatusEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a99616c93aaa6cd6b2ce081e5fb0f00502dc3aa
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/model/medtronicNg/StatusEvent.java
@@ -0,0 +1,301 @@
+package info.nightscout.android.model.medtronicNg;
+
+import java.util.Date;
+
+// Pump Data without Realm
+// So that we can unit test the upload code in a modular fashion,
+// without the Realm and Android Context dependencies.
+
+public class StatusEvent {
+
+    public StatusEvent(PumpStatusEvent pumpStatusEvent) {
+        eventDate = pumpStatusEvent.getEventDate();
+        pumpDate = pumpStatusEvent.getPumpDate();
+        deviceName = pumpStatusEvent.getDeviceName();
+        suspended = pumpStatusEvent.isSuspended();
+        bolusing = pumpStatusEvent.isBolusing();
+        deliveringInsulin = pumpStatusEvent.isDeliveringInsulin();
+        tempBasalActive = pumpStatusEvent.isTempBasalActive();
+        cgmActive = pumpStatusEvent.isCgmActive();
+        activeBasalPattern = pumpStatusEvent.getActiveBasalPattern();
+        basalRate = pumpStatusEvent.getBasalRate();
+        tempBasalRate = pumpStatusEvent.getTempBasalRate();
+        tempBasalPercentage = pumpStatusEvent.getTempBasalPercentage();
+        tempBasalMinutesRemaining = pumpStatusEvent.getTempBasalMinutesRemaining();
+        basalUnitsDeliveredToday = pumpStatusEvent.getBasalUnitsDeliveredToday();
+        batteryPercentage = pumpStatusEvent.getBatteryPercentage();
+        reservoirAmount = pumpStatusEvent.getReservoirAmount();
+        minutesOfInsulinRemaining = pumpStatusEvent.getMinutesOfInsulinRemaining();
+        activeInsulin = pumpStatusEvent.getActiveInsulin();
+        sgv = pumpStatusEvent.getSgv();
+        sgvDate = pumpStatusEvent.getSgvDate();
+        lowSuspendActive = pumpStatusEvent.isLowSuspendActive();
+        cgmTrend = pumpStatusEvent.getCgmTrendString();
+    }
+
+    public StatusEvent() {
+    }
+
+
+    private Date eventDate; // The actual time of the event (assume the capture device eventDate/time is accurate)
+    private Date pumpDate; // The eventDate/time on the pump at the time of the event
+    private String deviceName;
+
+    // Data from the Medtronic Pump Status message
+    private boolean suspended;
+    private boolean bolusing;
+    private boolean deliveringInsulin;
+    private boolean tempBasalActive;
+    private boolean cgmActive;
+    private byte activeBasalPattern;
+    private float basalRate;
+    private float tempBasalRate;
+    private byte tempBasalPercentage;
+    private short tempBasalMinutesRemaining;
+    private float basalUnitsDeliveredToday;
+    private short batteryPercentage;
+    private float reservoirAmount;
+    private short minutesOfInsulinRemaining; // 25h == "more than 1 day"
+    private float activeInsulin;
+    private int sgv;
+    private Date sgvDate;
+    private boolean lowSuspendActive;
+    private String cgmTrend;
+
+    private boolean recentBolusWizard; // Whether a bolus wizard has been run recently
+    private int bolusWizardBGL; // in mg/dL. 0 means no recent bolus wizard reading.
+
+    private long pumpTimeOffset; // millis the pump is ahead
+
+    private boolean uploaded = false;
+
+    public Date getEventDate() {
+        return eventDate;
+    }
+
+    public void setEventDate(Date eventDate) {
+        this.eventDate = eventDate;
+    }
+
+    public Date getPumpDate() {
+        return pumpDate;
+    }
+
+    public void setPumpDate(Date pumpDate) {
+        this.pumpDate = pumpDate;
+    }
+
+    public String getDeviceName() {
+        return deviceName;
+    }
+
+    public void setDeviceName(String deviceName) {
+        this.deviceName = deviceName;
+    }
+
+    public int getSgv() {
+        return sgv;
+    }
+
+    public void setSgv(int sgv) {
+        this.sgv = sgv;
+    }
+
+    public CGM_TREND getCgmTrend() {
+        return CGM_TREND.valueOf(cgmTrend);
+    }
+
+    public void setCgmTrend(CGM_TREND cgmTrend) {
+        this.cgmTrend = cgmTrend.name();
+    }
+
+    public void setCgmTrend(String cgmTrend) {
+        this.cgmTrend = cgmTrend;
+    }
+
+    public float getActiveInsulin() {
+        return activeInsulin;
+    }
+
+    public void setActiveInsulin(float activeInsulin) {
+        this.activeInsulin = activeInsulin;
+    }
+
+    public short getBatteryPercentage() {
+        return batteryPercentage;
+    }
+
+    public void setBatteryPercentage(short batteryPercentage) {
+        this.batteryPercentage = batteryPercentage;
+    }
+
+    public float getReservoirAmount() {
+        return reservoirAmount;
+    }
+
+    public void setReservoirAmount(float reservoirAmount) {
+        this.reservoirAmount = reservoirAmount;
+    }
+
+    public boolean hasRecentBolusWizard() {
+        return recentBolusWizard;
+    }
+
+    public int getBolusWizardBGL() {
+        return bolusWizardBGL;
+    }
+
+    public void setBolusWizardBGL(int bolusWizardBGL) {
+        this.bolusWizardBGL = bolusWizardBGL;
+    }
+
+    public boolean isUploaded() {
+        return uploaded;
+    }
+
+    public void setUploaded(boolean uploaded) {
+        this.uploaded = uploaded;
+    }
+
+    public boolean isSuspended() {
+        return suspended;
+    }
+
+    public void setSuspended(boolean suspended) {
+        this.suspended = suspended;
+    }
+
+    public boolean isBolusing() {
+        return bolusing;
+    }
+
+    public void setBolusing(boolean bolusing) {
+        this.bolusing = bolusing;
+    }
+
+    public boolean isDeliveringInsulin() {
+        return deliveringInsulin;
+    }
+
+    public void setDeliveringInsulin(boolean deliveringInsulin) {
+        this.deliveringInsulin = deliveringInsulin;
+    }
+
+    public boolean isTempBasalActive() {
+        return tempBasalActive;
+    }
+
+    public void setTempBasalActive(boolean tempBasalActive) {
+        this.tempBasalActive = tempBasalActive;
+    }
+
+    public boolean isCgmActive() {
+        return cgmActive;
+    }
+
+    public void setCgmActive(boolean cgmActive) {
+        this.cgmActive = cgmActive;
+    }
+
+    public byte getActiveBasalPattern() {
+        return activeBasalPattern;
+    }
+
+    public void setActiveBasalPattern(byte activeBasalPattern) {
+        this.activeBasalPattern = activeBasalPattern;
+    }
+
+    public float getBasalRate() {
+        return basalRate;
+    }
+
+    public void setBasalRate(float basalRate) {
+        this.basalRate = basalRate;
+    }
+
+    public float getTempBasalRate() {
+        return tempBasalRate;
+    }
+
+    public void setTempBasalRate(float tempBasalRate) {
+        this.tempBasalRate = tempBasalRate;
+    }
+
+    public byte getTempBasalPercentage() {
+        return tempBasalPercentage;
+    }
+
+    public void setTempBasalPercentage(byte tempBasalPercentage) {
+        this.tempBasalPercentage = tempBasalPercentage;
+    }
+
+    public short getTempBasalMinutesRemaining() {
+        return tempBasalMinutesRemaining;
+    }
+
+    public void setTempBasalMinutesRemaining(short tempBasalMinutesRemaining) {
+        this.tempBasalMinutesRemaining = tempBasalMinutesRemaining;
+    }
+
+    public float getBasalUnitsDeliveredToday() {
+        return basalUnitsDeliveredToday;
+    }
+
+    public void setBasalUnitsDeliveredToday(float basalUnitsDeliveredToday) {
+        this.basalUnitsDeliveredToday = basalUnitsDeliveredToday;
+    }
+
+    public short getMinutesOfInsulinRemaining() {
+        return minutesOfInsulinRemaining;
+    }
+
+    public void setMinutesOfInsulinRemaining(short minutesOfInsulinRemaining) {
+        this.minutesOfInsulinRemaining = minutesOfInsulinRemaining;
+    }
+
+    public Date getSgvDate() {
+        return sgvDate;
+    }
+
+    public void setSgvDate(Date sgvDate) {
+        this.sgvDate = sgvDate;
+    }
+
+    public boolean isLowSuspendActive() {
+        return lowSuspendActive;
+    }
+
+    public void setLowSuspendActive(boolean lowSuspendActive) {
+        this.lowSuspendActive = lowSuspendActive;
+    }
+
+    public boolean isRecentBolusWizard() {
+        return recentBolusWizard;
+    }
+
+    public void setRecentBolusWizard(boolean recentBolusWizard) {
+        this.recentBolusWizard = recentBolusWizard;
+    }
+
+    public long getPumpTimeOffset() {
+        return pumpTimeOffset;
+    }
+
+    public void setPumpTimeOffset(long pumpTimeOffset) {
+        this.pumpTimeOffset = pumpTimeOffset;
+    }
+
+    public enum CGM_TREND {
+            NONE,
+            DOUBLE_UP,
+            SINGLE_UP,
+            FOURTY_FIVE_UP,
+            FLAT,
+            FOURTY_FIVE_DOWN,
+            SINGLE_DOWN,
+            DOUBLE_DOWN,
+            NOT_COMPUTABLE,
+            RATE_OUT_OF_RANGE,
+            NOT_SET
+    }
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..8ed98bda91ef45a82af41b18e5c8917e7b223882
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java
@@ -0,0 +1,166 @@
+package info.nightscout.android.upload.nightscout;
+
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import info.nightscout.android.model.medtronicNg.StatusEvent;
+import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer;
+
+import android.support.annotation.NonNull;
+import info.nightscout.api.UploadApi;
+import info.nightscout.api.GlucoseEndpoints;
+import info.nightscout.api.BolusEndpoints.BolusEntry;
+import info.nightscout.api.GlucoseEndpoints.GlucoseEntry;
+import info.nightscout.api.BolusEndpoints;
+import info.nightscout.api.DeviceEndpoints;
+import info.nightscout.api.DeviceEndpoints.Iob;
+import info.nightscout.api.DeviceEndpoints.Battery;
+import info.nightscout.api.DeviceEndpoints.PumpStatus;
+import info.nightscout.api.DeviceEndpoints.PumpInfo;
+import info.nightscout.api.DeviceEndpoints.DeviceStatus;
+
+public class NightScoutUpload {
+
+    private static final String TAG = NightscoutUploadIntentService.class.getSimpleName();
+    private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
+
+    public NightScoutUpload () {
+
+    }
+
+    public Boolean doRESTUpload(String url,
+                                String secret,
+                                int uploaderBatteryLevel,
+                                List<StatusEvent> records) {
+        Boolean success = false;
+        try {
+            success = isUploaded(records, url, secret, uploaderBatteryLevel);
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to do REST API Upload to: " + url, e);
+        }
+        return success;
+    }
+
+
+    private boolean isUploaded(List<StatusEvent> records,
+                                 String baseURL,
+                                 String secret,
+                                 int uploaderBatteryLevel) throws Exception {
+
+        UploadApi uploadApi = new UploadApi(baseURL, formToken(secret));
+
+        boolean eventsUploaded = uploadEvents(uploadApi.getGlucoseEndpoints(),
+                 uploadApi.getBolusApi(),
+                 records );
+
+        boolean deviceStatusUploaded = uploadDeviceStatus(uploadApi.getDeviceEndpoints(),
+                uploaderBatteryLevel, records);
+
+        return eventsUploaded && deviceStatusUploaded;
+    }
+
+    private boolean uploadEvents(GlucoseEndpoints glucoseEndpoints,
+                                 BolusEndpoints bolusEndpoints,
+                                 List<StatusEvent> records ) throws Exception {
+
+
+        List<GlucoseEntry> glucoseEntries = new ArrayList<>();
+        List<BolusEntry> bolusEntries = new ArrayList<>();
+
+        for (StatusEvent record : records) {
+
+            GlucoseEntry  glucoseEntry = new GlucoseEntry();
+
+            glucoseEntry.setType("sgv");
+            glucoseEntry.setDirection(EntriesSerializer.getDirectionStringStatus(record.getCgmTrend()));
+            glucoseEntry.setDevice(record.getDeviceName());
+            glucoseEntry.setSgv(record.getSgv());
+            glucoseEntry.setDate(record.getEventDate().getTime());
+            glucoseEntry.setDateString(record.getEventDate().toString());
+
+            glucoseEntries.add(glucoseEntry);
+            glucoseEndpoints.sendEntries(glucoseEntries).execute();
+
+            BolusEntry  bolusEntry = new BolusEntry();
+
+            bolusEntry.setType("mbg");
+            bolusEntry.setDate(record.getEventDate().getTime());
+            bolusEntry.setDateString(record.getEventDate().toString());
+            bolusEntry.setDevice(record.getDeviceName());
+            bolusEntry.setMbg(record.getBolusWizardBGL());
+
+            bolusEntries.add(bolusEntry);
+            bolusEndpoints.sendEntries(bolusEntries).execute();
+
+        }
+
+         return true;
+    }
+
+    private boolean uploadDeviceStatus(DeviceEndpoints deviceEndpoints,
+                                       int uploaderBatteryLevel,
+                                       List<StatusEvent> records) throws Exception {
+
+
+        List<DeviceStatus> deviceEntries = new ArrayList<>();
+        for (StatusEvent record : records) {
+
+            Iob iob = new Iob(record.getPumpDate(), record.getActiveInsulin());
+            Battery battery = new Battery(record.getBatteryPercentage());
+            PumpStatus pumpstatus;
+            if (record.isBolusing()) {
+                pumpstatus = new PumpStatus(true, false, "");
+
+            } else if (record.isSuspended()) {
+                pumpstatus = new PumpStatus(false, true, "");
+            } else {
+                pumpstatus = new PumpStatus(false, false, "normal");
+            }
+
+            PumpInfo pumpInfo = new PumpInfo(
+                    ISO8601_DATE_FORMAT.format(record.getPumpDate()),
+                    new BigDecimal(record.getReservoirAmount()).setScale(3, BigDecimal.ROUND_HALF_UP),
+                    iob,
+                    battery,
+                    pumpstatus
+                    );
+
+            DeviceStatus deviceStatus = new DeviceStatus(
+                    uploaderBatteryLevel,
+                    record.getDeviceName(),
+                    ISO8601_DATE_FORMAT.format(record.getPumpDate()),
+                    pumpInfo
+            );
+
+            deviceEntries.add(deviceStatus);
+        }
+
+        for (DeviceStatus status: deviceEntries) {
+            deviceEndpoints.sendDeviceStatus(status).execute();
+        }
+
+        return true ;
+    }
+
+     @NonNull
+    private String formToken(String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException {
+        MessageDigest digest = MessageDigest.getInstance("SHA-1");
+        byte[] bytes = secret.getBytes("UTF-8");
+        digest.update(bytes, 0, bytes.length);
+        bytes = digest.digest();
+        StringBuilder sb = new StringBuilder(bytes.length * 2);
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java
index c613dfbb5112dad61676c85cd04ebe520c9b56af..07cba2e8fdbe2f7bc0ae100d436fdb619b78d910 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java
@@ -2,7 +2,6 @@ package info.nightscout.android.upload.nightscout;
 
 import retrofit2.Call;
 import retrofit2.http.GET;
-
 /**
  * Created by lgoedhart on 26/06/2016.
  */
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 6ac7129878dfdcf45118b3f1f4cf83538766de24..0c7c4e382a8624d4eb5da64452643b66f5ef98de 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
@@ -9,43 +9,25 @@ import android.net.NetworkInfo;
 import android.preference.PreferenceManager;
 import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.StatusLine;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.BasicResponseHandler;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.math.BigDecimal;
-import java.net.URL;
-import java.security.MessageDigest;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import info.nightscout.android.R;
 import info.nightscout.android.medtronic.MainActivity;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
-import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer;
+import info.nightscout.android.model.medtronicNg.StatusEvent;
 import io.realm.Realm;
 import io.realm.RealmResults;
 
 public class NightscoutUploadIntentService extends IntentService {
 
     private static final String TAG = NightscoutUploadIntentService.class.getSimpleName();
-    private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
-    private static final int SOCKET_TIMEOUT = 60 * 1000;
-    private static final int CONNECTION_TIMEOUT = 30 * 1000;
+
     Context mContext;
     private Realm mRealm;
+    private NightScoutUpload mNightScoutUpload;
 
     public NightscoutUploadIntentService() {
         super(NightscoutUploadIntentService.class.getName());
@@ -64,6 +46,7 @@ public class NightscoutUploadIntentService extends IntentService {
 
         Log.i(TAG, "onCreate called");
         mContext = this.getBaseContext();
+        mNightScoutUpload = new NightScoutUpload();
     }
 
     @Override
@@ -85,7 +68,18 @@ public class NightscoutUploadIntentService extends IntentService {
                 if (enableRESTUpload) {
                     long start = System.currentTimeMillis();
                     Log.i(TAG, String.format("Starting upload of %s record using a REST API", records.size()));
-                    doRESTUpload(prefs, records);
+                    String urlSetting = prefs.getString(mContext.getString(R.string.preference_nightscout_url), "");
+                    String secretSetting = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET");
+                    List<StatusEvent> statusEvents = getStatusEvents(records);
+                    int uploaderBatteryLevel = MainActivity.batLevel;
+                    Boolean uploadSuccess = mNightScoutUpload.doRESTUpload(urlSetting, secretSetting, uploaderBatteryLevel, statusEvents);
+                    if (uploadSuccess) {
+                        mRealm.beginTransaction();
+                        for (PumpStatusEvent updateRecord : records) {
+                            updateRecord.setUploaded(true);
+                        }
+                        mRealm.commitTransaction();
+                    }
                     Log.i(TAG, String.format("Finished upload of %s record using a REST API in %s ms", records.size(), System.currentTimeMillis() - start));
                 }
             } catch (Exception e) {
@@ -98,216 +92,16 @@ public class NightscoutUploadIntentService extends IntentService {
         NightscoutUploadReceiver.completeWakefulIntent(intent);
     }
 
-    private void doRESTUpload(SharedPreferences prefs, RealmResults<PumpStatusEvent> records) {
-        String apiScheme = "https://";
-        String apiUrl = "";
-        String apiSecret = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET");
-
-        // TODO - this code needs to go to the Settings Activity.
-        // Add the extra match for "KEY@" to support the previous single field
-        Pattern p = Pattern.compile("(.*\\/\\/)?(.*@)?([^\\/]*)(.*)");
-        Matcher m = p.matcher(prefs.getString(mContext.getString(R.string.preference_nightscout_url), ""));
-
-        if (m.find()) {
-            apiUrl = m.group(3);
-
-            // Only override apiSecret from URL (the "old" way), if the API secret preference is empty
-            if (apiSecret.equals("YOURAPISECRET") || apiSecret.equals("")) {
-                apiSecret = (m.group(2) == null) ? "" : m.group(2).replace("@", "");
-            }
-
-            // Override the URI scheme if it's been provided in the preference)
-            if (m.group(1) != null && !m.group(1).equals("")) {
-                apiScheme = m.group(1);
-            }
-        }
-
-        // Update the preferences to match what we expect. Only really used from converting from the
-        // old format to the new format. Aren't we nice for managing backward compatibility?
-        prefs.edit().putString(mContext.getString(R.string.preference_api_secret), apiSecret).apply();
-        prefs.edit().putString(mContext.getString(R.string.preference_nightscout_url), String.format("%s%s", apiScheme, apiUrl)).apply();
-
-        String uploadUrl = String.format("%s%s@%s/api/v1/", apiScheme, apiSecret, apiUrl);
-
-        try {
-            doRESTUploadTo(uploadUrl, records);
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to do REST API Upload to: " + uploadUrl, e);
+    private List<StatusEvent> getStatusEvents(RealmResults<PumpStatusEvent> records) {
+        List<StatusEvent> statusEvents = new ArrayList<>();
+        for (PumpStatusEvent record : records) {
+            StatusEvent event = new StatusEvent(record);
+            statusEvents.add(event);
         }
-    }
-
-    private void doRESTUploadTo(String baseURI, RealmResults<PumpStatusEvent> records) {
-        try {
-            String baseURL;
-            String secret = null;
-            String[] uriParts = baseURI.split("@");
-
-            if (uriParts.length == 1) {
-                throw new Exception("Starting with API v1, a pass phase is required");
-            } else if (uriParts.length == 2) {
-                secret = uriParts[0];
-                baseURL = uriParts[1];
-
-                // new format URL!
-                if (secret.contains("http")) {
-                    if (secret.contains("https")) {
-                        baseURL = "https://" + baseURL;
-                    } else {
-                        baseURL = "http://" + baseURL;
-                    }
-                    String[] uriParts2 = secret.split("//");
-                    secret = uriParts2[1];
-                }
-            } else {
-                throw new Exception(String.format("Unexpected baseURI: %s, uriParts.length: %s", baseURI, uriParts.length));
-            }
-
-            JSONArray devicestatusBody = new JSONArray();
-            JSONArray entriesBody = new JSONArray();
-
-            for (PumpStatusEvent record : records) {
-                addDeviceStatus(devicestatusBody, record);
-                addSgvEntry(entriesBody, record);
-                addMbgEntry(entriesBody, record);
-            }
-
-            boolean isUploaded = uploadToNightscout(new URL(baseURL + "/entries"), secret, entriesBody);
-
-            for(int i = 0; isUploaded && i < devicestatusBody.length(); i++) {
-                isUploaded &= uploadToNightscout(new URL(baseURL + "/devicestatus"), secret, devicestatusBody.getJSONObject(i));
-            }
-
-            if (isUploaded) {
-                // Yay! We uploaded. Tell Realm
-                // FIXME - check the upload succeeded!
-                mRealm.beginTransaction();
-                for (PumpStatusEvent updateRecord : records) {
-                    updateRecord.setUploaded(true);
-                }
-                mRealm.commitTransaction();
-            }
-
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to post data", e);
-        }
-    }
-
-    private boolean uploadToNightscout(URL endpoint, String secret, JSONObject httpBody) throws Exception {
-        return uploadToNightscout(endpoint, secret, httpBody.toString());
-    }
 
-    private boolean uploadToNightscout(URL endpoint, String secret, JSONArray httpBody) throws Exception {
-        return uploadToNightscout(endpoint, secret, httpBody.toString());
+        return statusEvents;
     }
 
-    private boolean uploadToNightscout(URL endpoint, String secret, String httpBody) throws Exception {
-        Log.i(TAG, "postURL: " + endpoint.toString());
-
-        HttpPost post = new HttpPost(endpoint.toString());
-
-        if (secret == null || secret.isEmpty()) {
-            throw new Exception("Starting with API v1, a pass phase is required");
-        } else {
-            MessageDigest digest = MessageDigest.getInstance("SHA-1");
-            byte[] bytes = secret.getBytes("UTF-8");
-            digest.update(bytes, 0, bytes.length);
-            bytes = digest.digest();
-            StringBuilder sb = new StringBuilder(bytes.length * 2);
-            for (byte b : bytes) {
-                sb.append(String.format("%02x", b & 0xff));
-            }
-            String token = sb.toString();
-            post.setHeader("api-secret", token);
-        }
-
-        HttpParams params = new BasicHttpParams();
-        HttpConnectionParams.setSoTimeout(params, SOCKET_TIMEOUT);
-        HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
-
-        DefaultHttpClient httpclient = new DefaultHttpClient(params);
-
-        Log.i(TAG, "Upload JSON: " + httpBody);
-
-        try {
-            StringEntity se = new StringEntity(httpBody);
-            post.setEntity(se);
-            post.setHeader("Accept", "application/json");
-            post.setHeader("Content-type", "application/json");
-
-            ResponseHandler responseHandler = new BasicResponseHandler();
-            httpclient.execute(post, responseHandler);
-        } catch (Exception e) {
-            Log.w(TAG, "Unable to post data to: '" + post.getURI().toString() + "'", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    private void addDeviceStatus(JSONArray devicestatusArray, PumpStatusEvent record) throws Exception {
-        JSONObject json = new JSONObject();
-        json.put("uploaderBattery", MainActivity.batLevel);
-        json.put("device", record.getDeviceName());
-        json.put("created_at", ISO8601_DATE_FORMAT.format(record.getPumpDate()));
-
-        JSONObject pumpInfo = new JSONObject();
-        pumpInfo.put("clock", ISO8601_DATE_FORMAT.format(record.getPumpDate()));
-        pumpInfo.put("reservoir", new BigDecimal(record.getReservoirAmount()).setScale(3, BigDecimal.ROUND_HALF_UP));
-
-        JSONObject iob = new JSONObject();
-        iob.put("timestamp", record.getPumpDate());
-        iob.put("bolusiob", record.getActiveInsulin());
-
-        JSONObject status = new JSONObject();
-        if (record.isBolusing()) {
-            status.put("bolusing", true);
-        } else if (record.isSuspended()) {
-            status.put("suspended", true);
-        } else {
-            status.put("status", "normal");
-        }
-
-        JSONObject battery = new JSONObject();
-        battery.put("percent", record.getBatteryPercentage());
-
-        pumpInfo.put("iob", iob);
-        pumpInfo.put("battery", battery);
-        pumpInfo.put("status", status);
-
-        json.put("pump", pumpInfo);
-        String jsonString = json.toString();
-        Log.i(TAG, "Device Status JSON: " + jsonString);
-
-        devicestatusArray.put(json);
-    }
-
-    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.getEventDate().getTime());
-        json.put("dateString", pumpRecord.getEventDate());
-
-        entriesArray.put(json);
-    }
-
-    private void addMbgEntry(JSONArray entriesArray, PumpStatusEvent pumpRecord) throws Exception {
-        if (pumpRecord.hasRecentBolusWizard()) {
-            JSONObject json = new JSONObject();
-
-            // TODO replace with Retrofit/EntriesSerializer
-            json.put("type", "mbg");
-            json.put("mbg", pumpRecord.getBolusWizardBGL());
-            json.put("device", pumpRecord.getDeviceName());
-            json.put("date", pumpRecord.getEventDate().getTime());
-            json.put("dateString", pumpRecord.getEventDate());
-
-            entriesArray.put(json);
-        }
-    }
 
     private boolean isOnline() {
         ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -320,4 +114,6 @@ public class NightscoutUploadIntentService extends IntentService {
 
         public static final String EXTENDED_DATA = "info.nightscout.android.upload.nightscout.DATA";
     }
+
+
 }
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java b/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
index 260b8c3b2acab0a24e81dd6c35dee9f9872f4e21..61785e93360db26a00d83a922beb25ed6c24ce2b 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
@@ -8,6 +8,7 @@ import com.google.gson.JsonSerializer;
 import java.lang.reflect.Type;
 
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
+import info.nightscout.android.model.medtronicNg.StatusEvent;
 
 /**
  * Created by lgoedhart on 26/06/2016.
@@ -42,6 +43,35 @@ public class EntriesSerializer implements JsonSerializer<PumpStatusEvent> {
         }
     }
 
+    public static String getDirectionStringStatus(StatusEvent.CGM_TREND trend) {
+        switch( trend ) {
+            case NONE:
+                return "NONE";
+            case DOUBLE_UP:
+                return "DoubleUp";
+            case SINGLE_UP:
+                return "SingleUp";
+            case FOURTY_FIVE_UP:
+                return "FortyFiveUp";
+            case FLAT:
+                return "Flat";
+            case FOURTY_FIVE_DOWN:
+                return "FortyFiveDown";
+            case SINGLE_DOWN:
+                return "SingleDown";
+            case DOUBLE_DOWN:
+                return "DoubleDown";
+            case NOT_COMPUTABLE:
+                return "NOT COMPUTABLE";
+            case RATE_OUT_OF_RANGE:
+                return "RATE OUT OF RANGE";
+            case NOT_SET:
+                return "NONE";
+            default:
+                return "NOT COMPUTABLE"; // TODO - should this be something else?
+        }
+    }
+
     @Override
     public JsonElement serialize(PumpStatusEvent src, Type typeOfSrc, JsonSerializationContext context) {
         final JsonObject jsonObject = new JsonObject();
diff --git a/app/src/main/java/info/nightscout/api/BolusEndpoints.java b/app/src/main/java/info/nightscout/api/BolusEndpoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..67d2291198532976c64d25eae16718087cb28f43
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/BolusEndpoints.java
@@ -0,0 +1,76 @@
+package info.nightscout.api;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+
+public interface BolusEndpoints {
+
+    class BolusEntry {
+        String type;
+        String dateString;
+        float date;
+        float mbg;
+        String device;
+
+        public BolusEntry() {  }
+
+        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 float getDate() {
+            return date;
+        }
+
+        public void setDate(float date) {
+            this.date = date;
+        }
+
+        public float getMbg() {
+            return mbg;
+        }
+
+        public void setMbg(float mbg) {
+            this.mbg = mbg;
+        }
+
+        public String getDevice() {
+            return device;
+        }
+
+        public void setDevice(String device) {
+            this.device = device;
+        }
+
+    }
+
+    @Headers({
+            "Accept: application/json",
+            "Content-type: application/json"
+    })
+    @POST("/api/v1/entries")
+    Call<ResponseBody> sendEntries(@Body List<BolusEntry> entries);
+
+}
+
+
+
diff --git a/app/src/main/java/info/nightscout/api/DeviceEndpoints.java b/app/src/main/java/info/nightscout/api/DeviceEndpoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..1bf66b24336e790d69c464ed1acb419c029d433d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/DeviceEndpoints.java
@@ -0,0 +1,97 @@
+package info.nightscout.api;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.Header;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+
+public interface DeviceEndpoints {
+
+    class Iob {
+        final Date timestamp;
+        final float bolusiob;
+        public Iob (Date timestamp,
+             float bolusiob) {
+            this.timestamp = timestamp;
+            this.bolusiob = bolusiob;
+        }
+    }
+
+    class Battery {
+        final short percent;
+        public Battery(short percent) {
+            this.percent = percent;
+        }
+    }
+
+    class PumpStatus {
+        final Boolean bolusing;
+        final Boolean suspended;
+        final String status;
+        public PumpStatus(
+                Boolean bolusing,
+                Boolean suspended,
+                String status
+
+        ) {
+            this.bolusing = bolusing;
+            this.suspended = suspended;
+            this.status = status;
+
+        }
+    }
+
+    class PumpInfo {
+        final String clock;
+        final BigDecimal reservoir;
+        final Iob iob;
+        final Battery battery;
+        final PumpStatus status;
+
+        public PumpInfo(String clock,
+                 BigDecimal reservoir,
+                 Iob iob,
+                 Battery battery,
+                 PumpStatus status) {
+            this.clock = clock;
+            this.reservoir = reservoir;
+            this.iob = iob;
+            this.battery = battery;
+            this.status = status;
+
+        }
+    }
+
+    class DeviceStatus {
+        final Integer uploaderBattery;
+        final String device;
+        final String created_at;
+        final PumpInfo pump;
+
+        public DeviceStatus(Integer uploaderBattery,
+                     String device,
+                     String created_at,
+                     PumpInfo pump) {
+            this.uploaderBattery = uploaderBattery;
+            this.device = device;
+            this.created_at = created_at;
+            this.pump = pump;
+        }
+    }
+
+    @Headers({
+            "Accept: application/json",
+            "Content-type: application/json"
+    })
+    @POST("/api/v1/devicestatus")
+    Call<ResponseBody> sendDeviceStatus(@Body DeviceStatus deviceStatus);
+
+}
+
+
+
diff --git a/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java b/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..07c1c10a8c2e60705ba348d7c9a0758216f74b1a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java
@@ -0,0 +1,89 @@
+package info.nightscout.api;
+
+
+
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.GET;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+
+public interface GlucoseEndpoints {
+
+    class GlucoseEntry {
+
+        String type;
+        String dateString;
+        float date;
+        float sgv;
+        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 float getDate() {
+            return date;
+        }
+
+        public void setDate(float date) {
+            this.date = date;
+        }
+
+        public float getSgv() {
+            return sgv;
+        }
+
+        public void setSgv(float 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() {  }
+    }
+
+    @Headers({
+            "Accept: application/json",
+            "Content-type: application/json"
+    })
+    @POST("/api/v1/entries")
+    Call<ResponseBody> sendEntries(@Body List<GlucoseEntry> entries);
+
+}
+
+
+
diff --git a/app/src/main/java/info/nightscout/api/UploadApi.java b/app/src/main/java/info/nightscout/api/UploadApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c429b7379d21f7342a199b7c50d1ff87aebe043
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/UploadApi.java
@@ -0,0 +1,78 @@
+package info.nightscout.api;
+
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.logging.HttpLoggingInterceptor;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class UploadApi {
+    private Retrofit retrofit;
+    private GlucoseEndpoints glucoseEndpoints;
+    private BolusEndpoints bolusApi;
+    private DeviceEndpoints deviceEndpoints;
+
+    public GlucoseEndpoints getGlucoseEndpoints() {
+        return glucoseEndpoints;
+    }
+
+    public BolusEndpoints getBolusApi() {
+        return bolusApi;
+    }
+
+    public DeviceEndpoints getDeviceEndpoints() {
+        return deviceEndpoints;
+    }
+
+    public UploadApi(String baseURL, String token) {
+
+        class AddAuthHeader implements Interceptor {
+
+            private String token;
+
+            public AddAuthHeader(String token) {
+                this.token = token;
+            }
+
+            @Override
+            public Response intercept(Interceptor.Chain chain) throws IOException {
+                Request original = chain.request();
+
+                Request.Builder requestBuilder = original.newBuilder()
+                        .header("api-secret", token)
+                        .method( original.method(), original.body());
+
+                Request request = requestBuilder.build();
+                return chain.proceed(request);
+            }
+        };
+
+        OkHttpClient.Builder okHttpClient = new OkHttpClient().newBuilder()
+                .connectTimeout(30, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS);
+
+        okHttpClient.addInterceptor(new AddAuthHeader(token));
+
+        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
+        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
+        okHttpClient.addInterceptor(logging);
+
+        retrofit = new Retrofit.Builder()
+                .baseUrl(baseURL)
+                .client(okHttpClient.build())
+                .addConverterFactory(GsonConverterFactory.create())
+                .build();
+
+        glucoseEndpoints = retrofit.create(GlucoseEndpoints.class);
+        bolusApi = retrofit.create(BolusEndpoints.class);
+        deviceEndpoints = retrofit.create(DeviceEndpoints.class);
+
+    }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 89751b6c042dc6aca1482597467d1d6cfffab63f..8665fb4b355532d11319c8d9ee3a86311eae30af 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -31,8 +31,6 @@
     <string name="error_class_not_found_exception">Application code error.</string>
     <string name="error_http_response">Server responded with error. Could be username or password problem.</string>
     <string name="error_field_required">This field is required</string>
-    <string name="preference_nightscout_url">Nightscout URL</string>
-    <string name="preference_api_secret">API SECRET</string>
     <string name="prompt_carelink_username_password">Please enter your CareLink details.\nThey will not be stored.</string>
     <string name="close">Close</string>
     <string name="register_contour_next_link">Registered Devices</string>
@@ -55,4 +53,6 @@
     <string name="dummy_button">Dummy Button</string>
     <string name="dummy_content">DUMMY\nCONTENT</string>
     <string name="menu_name_status">Status</string>
+    <string name="preference_api_secret">YOUR.API.SECRET</string>
+    <string name="preference_nightscout_url">YOUR.NIGHTSCOUT.URL</string>
 </resources>
diff --git a/app/src/testDebug/java/info/nightscout/android/upload/nightscout/NightScoutUploadTest.java b/app/src/testDebug/java/info/nightscout/android/upload/nightscout/NightScoutUploadTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b46150ac0bbd03f7debe5699e9868efc28ad960b
--- /dev/null
+++ b/app/src/testDebug/java/info/nightscout/android/upload/nightscout/NightScoutUploadTest.java
@@ -0,0 +1,79 @@
+package info.nightscout.android.upload.nightscout;
+
+import android.util.Log;
+
+import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
+import info.nightscout.android.model.medtronicNg.StatusEvent;
+
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({Log.class})
+public class NightScoutUploadTest {
+
+    NightScoutUpload mUploader;
+    List<StatusEvent> mEvents;
+
+    @Before
+    public void doSetup() {
+
+        mUploader = new NightScoutUpload();
+
+        mEvents = new ArrayList<StatusEvent>();
+
+        StatusEvent event1 = new StatusEvent();
+        Date date = new Date();
+        event1.setEventDate(date);
+        event1.setPumpDate(date);
+        event1.setDeviceName("MyDevice");
+        event1.setSgv(100);
+        event1.setCgmTrend(StatusEvent.CGM_TREND.FLAT);
+        event1.setActiveInsulin(5.0f);
+        event1.setBatteryPercentage((short)100);
+        event1.setReservoirAmount(50.0f);
+        event1.setRecentBolusWizard(false);
+        event1.setBolusWizardBGL(100);
+        event1.setUploaded(false);
+        event1.setSuspended(false);
+        event1.setDeliveringInsulin(false);
+        event1.setTempBasalActive(false);
+        event1.setCgmActive(false);
+        event1.setActiveBasalPattern((byte)42);
+        event1.setBasalRate(1.0f);
+        event1.setTempBasalPercentage((byte)80);
+        event1.setTempBasalMinutesRemaining((short)30);
+        event1.setBasalUnitsDeliveredToday(30.0f);
+        event1.setMinutesOfInsulinRemaining((short)45);
+        event1.setSgvDate(date);
+        event1.setLowSuspendActive(false);
+        event1.setPumpTimeOffset(100000);
+
+        mEvents.add(event1);
+
+    }
+
+    @Test
+    public void doTest() {
+        PowerMockito.mockStatic(Log.class);
+        String url =  "https://my.azurewebsites.net";
+        String secret = "SECRET";
+        int uploaderBatteryLevel = 50;
+
+        Boolean success = mUploader.doRESTUpload(url, secret, uploaderBatteryLevel, mEvents);
+        assertEquals(success, true);
+    }
+
+}
\ No newline at end of file