Skip to content

Commit 6ce7387

Browse files
authored
Merge pull request #3859 from benceszasz/master
CareLinkFollower - v11 data endpoint outside US
2 parents 194b595 + 2baa087 commit 6ce7387

18 files changed

+376
-51
lines changed

app/proguard-debug.pro

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,13 @@
5858

5959
-keep class com.newrelic.** { *; }
6060
-dontwarn com.newrelic.**
61-
-keepattributes Exceptions, Signature, InnerClasses, LineNumberTable, SourceFile, EnclosingMethod
61+
-keepattributes Exceptions, Signature, InnerClasses, LineNumberTable, SourceFile, EnclosingMethod
62+
63+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.*
64+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.*
65+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.** { *; }
66+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.** { *; }
67+
-keep class * extends com.google.gson.TypeAdapter
68+
-keep class * implements com.google.gson.TypeAdapterFactory
69+
-keep class * implements com.google.gson.JsonSerializer
70+
-keep class * implements com.google.gson.JsonDeserializer

app/proguard-rules.pro

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,11 @@
149149
-dontwarn com.newrelic.**
150150
-keepattributes Exceptions, Signature, InnerClasses, LineNumberTable
151151

152-
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.*
152+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.*
153+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.*
154+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.** { *; }
155+
-keep class com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.** { *; }
156+
-keep class * extends com.google.gson.TypeAdapter
157+
-keep class * implements com.google.gson.TypeAdapterFactory
158+
-keep class * implements com.google.gson.JsonSerializer
159+
-keep class * implements com.google.gson.JsonDeserializer

app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/CareLinkDataProcessor.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static synchronized void processData(final RecentData recentData, final boolean
7373
filteredSgList = new ArrayList<>();
7474
for (SensorGlucose sg : recentData.sgs) {
7575
//SG DateTime is null (sensor expired?)
76-
if (sg != null && sg.datetimeAsDate != null) {
76+
if (sg != null && sg.getDate() != null) {
7777
filteredSgList.add(sg);
7878
}
7979
}
@@ -84,31 +84,31 @@ static synchronized void processData(final RecentData recentData, final boolean
8484
sensor.save();
8585

8686
// place in order of oldest first
87-
Collections.sort(filteredSgList, (o1, o2) -> o1.datetimeAsDate.compareTo(o2.datetimeAsDate));
87+
Collections.sort(filteredSgList, (o1, o2) -> o1.getDate().compareTo(o2.getDate()));
8888

8989
for (final SensorGlucose sg : filteredSgList) {
9090

9191
//Not EPOCH 0 (warmup?)
92-
if (sg.datetimeAsDate.getTime() > 1) {
92+
if (sg.getDate().getTime() > 1) {
9393

9494
//Not in the future
95-
if (sg.datetimeAsDate.getTime() < new Date().getTime() + 300_000) {
95+
if (sg.getDate().getTime() < new Date().getTime() + 300_000) {
9696

9797
//Not 0 SG (not calibrated?)
9898
if (sg.sg > 0) {
9999

100100
//newer than last BG
101-
if (sg.datetimeAsDate.getTime() > lastBgTimestamp) {
101+
if (sg.getDate().getTime() > lastBgTimestamp) {
102102

103-
if (sg.datetimeAsDate.getTime() > 0) {
103+
if (sg.getDate().getTime() > 0) {
104104

105105
//New entry
106-
if (BgReading.getForPreciseTimestamp(sg.datetimeAsDate.getTime(), 10_000) == null) {
106+
if (BgReading.getForPreciseTimestamp(sg.getDate().getTime(), 10_000) == null) {
107107
UserError.Log.d(TAG, "NEW NEW NEW New entry: " + sg.toS());
108108

109109
if (live) {
110110
final BgReading bg = new BgReading();
111-
bg.timestamp = sg.datetimeAsDate.getTime();
111+
bg.timestamp = sg.getDate().getTime();
112112
bg.calculated_value = (double) sg.sg;
113113
bg.raw_data = SPECIAL_FOLLOWER_PLACEHOLDER;
114114
bg.filtered_data = (double) sg.sg;
@@ -149,25 +149,25 @@ static synchronized void processData(final RecentData recentData, final boolean
149149
//Filter markers
150150
filteredMarkerList = new ArrayList<>();
151151
for (Marker marker : recentData.markers) {
152-
if (marker != null && marker.type != null && marker.dateTime != null) {
152+
if (marker != null && marker.type != null && marker.getDate() != null) {
153153
filteredMarkerList.add(marker);
154154
}
155155
}
156156

157157
if (filteredMarkerList.size() > 0) {
158158
//sort markers by time
159-
Collections.sort(filteredMarkerList, (o1, o2) -> o1.dateTime.compareTo(o2.dateTime));
159+
Collections.sort(filteredMarkerList, (o1, o2) -> o1.getDate().compareTo(o2.getDate()));
160160

161161
//process markers one-by-one
162162
for (Marker marker : filteredMarkerList) {
163163

164164
//FINGER BG
165165
if (marker.isBloodGlucose() && Pref.getBooleanDefaultFalse("clfollow_download_finger_bgs")) {
166166
//check required values
167-
if (marker.value != null && !marker.value.equals(0)) {
167+
if (marker.getBloodGlucose() != null && !marker.getBloodGlucose().equals(0)) {
168168
//new blood test
169-
if (BloodTest.getForPreciseTimestamp(marker.dateTime.getTime(), 10000) == null) {
170-
BloodTest.create(marker.dateTime.getTime(), marker.value, SOURCE_CARELINK_FOLLOW);
169+
if (BloodTest.getForPreciseTimestamp(marker.getDate().getTime(), 10000) == null) {
170+
BloodTest.create(marker.getDate().getTime(), marker.getBloodGlucose(), SOURCE_CARELINK_FOLLOW);
171171
}
172172
}
173173

@@ -186,24 +186,24 @@ static synchronized void processData(final RecentData recentData, final boolean
186186
//Insulin
187187
if (marker.type.equals(Marker.MARKER_TYPE_INSULIN)) {
188188
carbs = 0;
189-
if (marker.deliveredExtendedAmount != null && marker.deliveredFastAmount != null) {
190-
insulin = marker.deliveredExtendedAmount + marker.deliveredFastAmount;
189+
if (marker.getInsulinAmount() != null) {
190+
insulin = marker.getInsulinAmount();
191191
}
192192
//SKIP if insulin = 0
193193
if (insulin == 0) continue;
194194
//Carbs
195195
} else if (marker.type.equals(Marker.MARKER_TYPE_MEAL)) {
196-
if (marker.amount != null) {
197-
carbs = marker.amount;
196+
if (marker.getCarbAmount() != null) {
197+
carbs = marker.getCarbAmount();
198198
}
199199
insulin = 0;
200200
//SKIP if carbs = 0
201201
if (carbs == 0) continue;
202202
}
203203

204204
//new Treatment
205-
if (newTreatment(carbs, insulin, marker.dateTime.getTime())) {
206-
t = Treatments.create(carbs, insulin, marker.dateTime.getTime());
205+
if (newTreatment(carbs, insulin, marker.getDate().getTime())) {
206+
t = Treatments.create(carbs, insulin, marker.getDate().getTime());
207207
if (t != null) {
208208
t.enteredBy = SOURCE_CARELINK_FOLLOW;
209209
t.save();
@@ -222,7 +222,7 @@ static synchronized void processData(final RecentData recentData, final boolean
222222
//PUMP INFO (Pump Status)
223223
if (recentData.isNGP()) {
224224
PumpStatus.setReservoir(recentData.reservoirRemainingUnits);
225-
PumpStatus.setBattery(recentData.medicalDeviceBatteryLevelPercent);
225+
PumpStatus.setBattery(recentData.getDeviceBatteryLevel());
226226
if (recentData.activeInsulin != null)
227227
PumpStatus.setBolusIoB(recentData.activeInsulin.amount);
228228
PumpStatus.syncUpdate();
@@ -246,13 +246,13 @@ static synchronized void processData(final RecentData recentData, final boolean
246246
//Active Notifications
247247
if (recentData.notificationHistory.activeNotifications != null) {
248248
for (ActiveNotification activeNotification : recentData.notificationHistory.activeNotifications) {
249-
addNotification(activeNotification.dateTime, recentData.getDeviceFamily(), activeNotification.messageId, activeNotification.faultId);
249+
addNotification(activeNotification.dateTime, recentData.getDeviceFamily(), activeNotification.getMessageId(), activeNotification.faultId);
250250
}
251251
}
252252
//Cleared Notifications
253253
if (recentData.notificationHistory.clearedNotifications != null) {
254254
for (ClearedNotification clearedNotification : recentData.notificationHistory.clearedNotifications) {
255-
addNotification(clearedNotification.triggeredDateTime, recentData.getDeviceFamily(), clearedNotification.messageId, clearedNotification.faultId);
255+
addNotification(clearedNotification.triggeredDateTime, recentData.getDeviceFamily(), clearedNotification.getMessageId(), clearedNotification.faultId);
256256
}
257257
}
258258
}

app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/client/CareLinkClient.java

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.ClearedNotification;
99
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.CountrySettings;
1010
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.DataUpload;
11+
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.DisplayMessage;
1112
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.Marker;
1213
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.MonitorData;
1314
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.Profile;
@@ -53,6 +54,9 @@ public class CareLinkClient {
5354
protected String carelinkCountry;
5455
protected static final String CARELINK_CONNECT_SERVER_EU = "carelink.minimed.eu";
5556
protected static final String CARELINK_CONNECT_SERVER_US = "carelink.minimed.com";
57+
protected static final String CARELINK_CLOUD_SERVER_EU = "clcloud.minimed.eu";
58+
protected static final String CARELINK_CLOUD_SERVER_US = "clcloud.minimed.com";
59+
protected static final String API_PATH_DISPLAY_MESSAGE = "connect/carepartner/v11/display/message";
5660
protected static final String CARELINK_LANGUAGE_EN = "en";
5761
protected static final String CARELINK_AUTH_TOKEN_COOKIE_NAME = "auth_tmp_token";
5862
protected static final String CARELINK_TOKEN_VALIDTO_COOKIE_NAME = "c_token_valid_to";
@@ -197,6 +201,12 @@ protected String careLinkServer() {
197201
return CARELINK_CONNECT_SERVER_EU;
198202
}
199203

204+
protected String cloudServer() {
205+
if (this.carelinkCountry.equals("us"))
206+
return CARELINK_CLOUD_SERVER_US;
207+
else
208+
return CARELINK_CLOUD_SERVER_EU;
209+
}
200210

201211
//Wrapper for common request of recent data (last 24 hours)
202212
public RecentData getRecentData() {
@@ -619,10 +629,14 @@ public RecentData getLast24Hours() {
619629
// Periodic data from CareLink Cloud
620630
public RecentData getConnectDisplayMessage(String username, String role, String patientUsername, String endpointUrl) {
621631

622-
RequestBody requestBody = null;
623-
Gson gson = null;
624-
JsonObject userJson = null;
632+
RequestBody requestBody;
633+
Gson gson;
634+
JsonObject userJson;
625635
RecentData recentData = null;
636+
DisplayMessage displayMessage;
637+
boolean useNewEndpoint;
638+
HttpUrl newEndpointUrl;
639+
626640

627641
// Build user json for request
628642
userJson = new JsonObject();
@@ -635,10 +649,33 @@ public RecentData getConnectDisplayMessage(String username, String role, String
635649

636650
requestBody = RequestBody.create(MediaType.get("application/json; charset=utf-8"), gson.toJson(userJson));
637651

652+
//use new v11 endpoint outside US
653+
useNewEndpoint = !this.carelinkCountry.equals("us") ? true : false;
654+
655+
//new endpoint url
656+
newEndpointUrl = new HttpUrl.Builder()
657+
.scheme("https")
658+
.host(this.cloudServer())
659+
.addPathSegments(API_PATH_DISPLAY_MESSAGE)
660+
.build();
661+
662+
//get data and correct time
638663
try {
639-
recentData = this.getData(HttpUrl.parse(endpointUrl), requestBody, RecentData.class);
640-
if (recentData != null)
641-
correctTimeInRecentData(recentData);
664+
//Use old data format for old endpoint
665+
if (!useNewEndpoint) {
666+
recentData = this.getData(HttpUrl.parse(endpointUrl), requestBody, RecentData.class);
667+
if (recentData != null) {
668+
correctTimeInRecentData(recentData);
669+
}
670+
}
671+
//Use new data format outside US
672+
else {
673+
displayMessage = this.getData(newEndpointUrl, requestBody, DisplayMessage.class);
674+
if (displayMessage != null && displayMessage.patientData != null) {
675+
correctTimeInDisplayMessage(displayMessage);
676+
recentData = displayMessage.patientData;
677+
}
678+
}
642679
} catch (Exception e) {
643680
lastErrorMessage = e.getClass().getSimpleName() + ":" + e.getMessage();
644681
}
@@ -668,6 +705,11 @@ public RecentData getM2MPatientData(String patientUsername) {
668705
}
669706

670707
// General data request for API calls
708+
709+
protected <T> T getData(String host, String path, RequestBody requestBody, Class<T> dataClass) {
710+
return this.getData(new HttpUrl.Builder().scheme("https").host(host).addPathSegments(path).build(), requestBody, dataClass);
711+
}
712+
671713
protected <T> T getData(HttpUrl url, RequestBody requestBody, Class<T> dataClass) {
672714

673715
Request.Builder requestBuilder = null;
@@ -774,6 +816,65 @@ protected void addHttpHeaders(Request.Builder requestBuilder, RequestType type,
774816

775817
}
776818

819+
protected void correctTimeInDisplayMessage(DisplayMessage displayMessage) {
820+
821+
boolean timezoneMissing = false;
822+
String offsetString = null;
823+
RecentData recentData = null;
824+
825+
recentData = displayMessage.patientData;
826+
827+
//time data is available to check and correct time if needed
828+
if (recentData.lastConduitDateTime != null && recentData.lastConduitDateTime.getTime() > 1
829+
&& recentData.lastConduitUpdateServerDateTime > 1) {
830+
831+
//Correct times if server <> device > 26 mins => possibly different time zones
832+
int diffInHour = (int) Math.round(((recentData.lastConduitUpdateServerDateTime - recentData.lastConduitDateTime.getTime()) / 3600000D));
833+
if (diffInHour != 0 && diffInHour < 26) {
834+
835+
recentData.lastConduitDateTime = shiftDateByHours(recentData.lastConduitDateTime, diffInHour);
836+
837+
//Sensor glucose
838+
if (recentData.sgs != null) {
839+
for (SensorGlucose sg : recentData.sgs) {
840+
if(sg.timestamp != null)
841+
sg.timestamp = shiftDateByHours(sg.timestamp, diffInHour);
842+
}
843+
}
844+
845+
//Markers
846+
if (recentData.markers != null) {
847+
for (Marker marker : recentData.markers) {
848+
if(marker.timestamp != null)
849+
marker.timestamp = shiftDateByHours(marker.timestamp, diffInHour);
850+
}
851+
}
852+
//Notifications
853+
if (recentData.notificationHistory != null) {
854+
if (recentData.notificationHistory.clearedNotifications != null) {
855+
for (ClearedNotification notification : recentData.notificationHistory.clearedNotifications) {
856+
if(notification.dateTime != null) {
857+
notification.dateTime = shiftDateByHours(notification.dateTime, diffInHour);
858+
notification.triggeredDateTime = shiftDateByHours(notification.triggeredDateTime, diffInHour);
859+
}
860+
}
861+
}
862+
if (recentData.notificationHistory.activeNotifications != null) {
863+
for (ActiveNotification notification : recentData.notificationHistory.activeNotifications) {
864+
if(notification.dateTime != null)
865+
notification.dateTime = shiftDateByHours(notification.dateTime, diffInHour);
866+
}
867+
}
868+
}
869+
870+
}
871+
872+
}
873+
874+
displayMessage.patientData = recentData;
875+
876+
}
877+
777878
protected void correctTimeInRecentData(RecentData recentData) {
778879

779880
boolean timezoneMissing = false;

app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/message/ActiveInsulin.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.eveningoutpost.dexdrip.cgm.carelinkfollow.message;
22

3+
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.CareLinkJsonAdapter;
4+
import com.google.gson.annotations.JsonAdapter;
5+
36
import java.util.Date;
47

58
/**
@@ -8,6 +11,7 @@
811
public class ActiveInsulin {
912

1013
public Integer code;
14+
@JsonAdapter(CareLinkJsonAdapter.class)
1115
public Date datetime;
1216
public long version;
1317
public Double amount;
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
package com.eveningoutpost.dexdrip.cgm.carelinkfollow.message;
22

3+
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.CareLinkJsonAdapter;
4+
import com.google.gson.annotations.JsonAdapter;
5+
36
import java.util.Date;
47

5-
public class ActiveNotification {
8+
public class ActiveNotification extends Notification {
69

710
public String GUID;
8-
public Date dateTime;
9-
public String type;
10-
public int faultId;
11-
public int instanceId;
12-
public String messageId;
13-
public String pumpDeliverySuspendState;
14-
public String pnpId;
15-
public int relativeOffset;
11+
1612
public Boolean alertSilenced;
1713

14+
1815
}

app/src/main/java/com/eveningoutpost/dexdrip/cgm/carelinkfollow/message/Alarm.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.eveningoutpost.dexdrip.cgm.carelinkfollow.message;
22

3+
import com.eveningoutpost.dexdrip.cgm.carelinkfollow.message.util.CareLinkJsonAdapter;
4+
import com.google.gson.annotations.JsonAdapter;
5+
36
import java.util.Date;
47

58
/**
@@ -12,6 +15,7 @@ public String getMessageAlarmCode() {
1215
}
1316

1417
public int code;
18+
//@JsonAdapter(CareLinkJsonAdapter.class)
1519
public String datetime;
1620
public Date datetimeAsDate;
1721
public String type;

0 commit comments

Comments
 (0)