diff --git a/app/app.iml b/app/app.iml index 4a4fdfa8b64515772718c9fc5fc9405c90a3e6b5..e31111587bb9475b2dd7f710c44e347710cea142 100644 --- a/app/app.iml +++ b/app/app.iml @@ -65,14 +65,6 @@ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" /> @@ -81,18 +73,26 @@ <sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/21.0.3/jars" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.crashlytics.sdk.android/answers/1.3.6/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.crashlytics.sdk.android/beta/1.1.4/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.crashlytics.sdk.android/crashlytics-core/2.3.8/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.crashlytics.sdk.android/crashlytics/2.5.5/jars" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.github.satyan/sugar/1.4/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/io.fabric.sdk.android/fabric/1.3.10/jars" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" /> @@ -103,6 +103,7 @@ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" /> + <excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> @@ -114,18 +115,16 @@ </content> <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" /> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="library" exported="" name="guava-18.0" level="project" /> <orderEntry type="library" exported="" name="physicaloidlibrary" level="project" /> <orderEntry type="library" exported="" name="crashlytics-2.5.5" level="project" /> - <orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" /> - <orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" /> + <orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" /> <orderEntry type="library" exported="" name="crashlytics-core-2.3.8" level="project" /> <orderEntry type="library" exported="" name="beta-1.1.4" level="project" /> - <orderEntry type="library" exported="" name="sugar-1.4" level="project" /> <orderEntry type="library" exported="" name="logback-android-1.1.1-3" level="project" /> <orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" /> <orderEntry type="library" exported="" name="mongo-java-driver-3.0.2" level="project" /> <orderEntry type="library" exported="" name="commons-lang3-3.4" level="project" /> + <orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" /> <orderEntry type="library" exported="" name="slf4j-api-1.7.2" level="project" /> <orderEntry type="library" exported="" name="answers-1.3.6" level="project" /> <orderEntry type="library" exported="" name="fabric-1.3.10" level="project" /> diff --git a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCNLReader.java b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCNLReader.java index 7457a77357f3ca25235f7fc50beda35d00b83047..68b71afff66506776dcfd1314fa8452b2b945972 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCNLReader.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCNLReader.java @@ -23,6 +23,7 @@ import info.nightscout.android.medtronic.message.ReadInfoResponseMessage; import info.nightscout.android.medtronic.message.UnexpectedMessageException; import info.nightscout.android.medtronic.service.MedtronicCNLService; import info.nightscout.android.upload.MedtronicNG.CGMRecord; +import info.nightscout.android.upload.MedtronicNG.PumpStatusRecord; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -267,7 +268,7 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler { readMessage(); } - public void getPumpTime(CGMRecord pumpRecord) throws EncryptionException, IOException, ChecksumException, TimeoutException { + public void getPumpTime(PumpStatusRecord pumpRecord) throws EncryptionException, IOException, ChecksumException, TimeoutException { // FIXME - throw if not in EHSM mode (add a state machine) new PumpTimeRequestMessage(mPumpSession).send(this); @@ -295,10 +296,9 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); pumpRecord.displayTime = dateFormat.format(pumpDate); - Medtronic640gActivity.pumpStatusRecord.pumpDate = pumpDate; } - public void getPumpStatus(CGMRecord pumpRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException { + public void getPumpStatus(CGMRecord cgmRecord) throws IOException, EncryptionException, ChecksumException, TimeoutException { // FIXME - throw if not in EHSM mode (add a state machine) new PumpStatusRequestMessage(mPumpSession).send(this); @@ -321,21 +321,21 @@ public class MedtronicCNLReader implements ContourNextLinkMessageHandler { // Read the data into the record long rawActiveInsulin = statusBuffer.getShort(0x33) & 0x0000ffff; Medtronic640gActivity.pumpStatusRecord.activeInsulin = new BigDecimal( rawActiveInsulin / 10000f ).setScale(3, BigDecimal.ROUND_HALF_UP); - pumpRecord.sgv = statusBuffer.getShort(0x35) & 0x0000ffff; // In mg/DL. 0 means no CGM reading + cgmRecord.sgv = statusBuffer.getShort(0x35) & 0x0000ffff; // In mg/DL. 0 means no CGM reading long rtc; long offset; - if( ( pumpRecord.sgv & 0x200 ) == 0x200 ) { + if( ( cgmRecord.sgv & 0x200 ) == 0x200 ) { // Sensor error. Let's reset. FIXME - solve this more elegantly later - pumpRecord.sgv = 0; + cgmRecord.sgv = 0; rtc = 0; offset = 0; - pumpRecord.setTrend(CGMRecord.TREND.NOT_SET); + cgmRecord.setTrend(CGMRecord.TREND.NOT_SET); } else { rtc = statusBuffer.getInt(0x37) & 0x00000000ffffffffL; offset = statusBuffer.getInt(0x3b); - pumpRecord.setTrend(CGMRecord.fromMessageByte( statusBuffer.get(0x40))); + cgmRecord.setTrend(CGMRecord.fromMessageByte( statusBuffer.get(0x40))); } - pumpRecord.sgvDate = MessageUtils.decodeDateTime(rtc, offset); + cgmRecord.sgvDate = MessageUtils.decodeDateTime(rtc, offset); Medtronic640gActivity.pumpStatusRecord.recentBolusWizard = statusBuffer.get(0x48) != 0; Medtronic640gActivity.pumpStatusRecord.bolusWizardBGL = statusBuffer.getShort(0x49); // In mg/DL long rawReservoirAmount = statusBuffer.getInt(0x2b) & 0xffffffff; diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCNLService.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCNLService.java index 8a19fb13fd062822173c2b66dd7cee248597f8cc..9130afac0b91548d0bc5d0e6a7470d5541ccc3fa 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCNLService.java +++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCNLService.java @@ -1,8 +1,5 @@ package info.nightscout.android.medtronic.service; -import android.annotation.SuppressLint; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -12,8 +9,20 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Handler; import android.os.Message; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; import android.util.Log; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeoutException; + import info.nightscout.android.R; import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.Medtronic640gActivity; @@ -25,19 +34,9 @@ import info.nightscout.android.medtronic.message.MessageUtils; import info.nightscout.android.medtronic.message.UnexpectedMessageException; import info.nightscout.android.service.AbstractService; import info.nightscout.android.upload.MedtronicNG.CGMRecord; +import info.nightscout.android.upload.MedtronicNG.PumpStatusRecord; import info.nightscout.android.upload.UploadHelper; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.TimeoutException; - -@SuppressLint("NewApi") public class MedtronicCNLService extends AbstractService { public final static int USB_VID = 0x1a79; public final static int USB_PID = 0x6210; @@ -47,7 +46,10 @@ public class MedtronicCNLService extends AbstractService { private static final String TAG = MedtronicCNLService.class.getSimpleName(); private Context mContext; private NotificationManagerCompat nm; - private final static long FIVE_MINS_MS = 300000L; + private final static long POLL_PERIOD_MS = 300000L; + private final static long POLL_DELAY_MS = 30000L; + // If the polling is within this many milliseconds (either side), then we don't reset the timer + private final static long POLL_MARGIN_MS = 10000L; private UsbManager mUsbManager; private Handler handler; @@ -65,6 +67,10 @@ public class MedtronicCNLService extends AbstractService { // Add a small start delay - for some reason, having no start delay causes initial // binding/rendering issues + startPollingLoop(250L); + } + + private void startPollingLoop(long delay) { mTimer.scheduleAtFixedRate(new TimerTask() { public void run() { handler.post(new Runnable() { @@ -73,7 +79,7 @@ public class MedtronicCNLService extends AbstractService { } }); } - }, 250, FIVE_MINS_MS); + }, delay, POLL_PERIOD_MS); } @Override @@ -106,15 +112,12 @@ public class MedtronicCNLService extends AbstractService { mHidDevice = UsbHidDriver.acquire(mUsbManager, USB_VID, USB_PID); // Load the initial data to the display - CGMRecord pumpRecord = loadData(); - send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_DATA, pumpRecord)); + CGMRecord cgmRecord = loadData(); + PumpStatusRecord pumpRecord = Medtronic640gActivity.pumpStatusRecord; - if (!isOnline()) { - String title = "Internet connection error"; - String msg = "Please check that you're connected to the Internet"; - //showNotification(title, msg); - send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_ERROR, title + "\n" + msg)); - } else if (mHidDevice == null) { + send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_DATA, cgmRecord)); + + if (mHidDevice == null) { String title = "USB connection error"; String msg = "Is the Bayer Contour NextLink plugged in?"; //showNotification(title, msg); @@ -140,7 +143,7 @@ public class MedtronicCNLService extends AbstractService { String hmac = configDbHelper.getHmac(cnlReader.getStickSerial()); String key = configDbHelper.getKey(cnlReader.getStickSerial()); String deviceName = String.format("medtronic-640g://%s", cnlReader.getStickSerial()); - pumpRecord.setDeviceName(deviceName); + cgmRecord.setDeviceName(deviceName); Medtronic640gActivity.pumpStatusRecord.setDeviceName(deviceName); if (hmac.equals("") || key.equals("")) { @@ -166,9 +169,12 @@ public class MedtronicCNLService extends AbstractService { cnlReader.beginEHSMSession(); cnlReader.getPumpTime(pumpRecord); - cnlReader.getPumpStatus(pumpRecord); - writeData(pumpRecord); - send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_DATA, pumpRecord)); + cnlReader.getPumpStatus(cgmRecord); + + long pumpToUploaderTimeOffset = (new java.util.Date()).getTime() - Medtronic640gActivity.pumpStatusRecord.pumpDate.getTime(); + + writeData(cgmRecord); + send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_DATA, cgmRecord)); cnlReader.endEHSMSession(); } cnlReader.closeConnection(); @@ -196,7 +202,15 @@ public class MedtronicCNLService extends AbstractService { send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_ERROR, "Could not close connection: " + e.getMessage())); } - mUploader.execute(pumpRecord); + // TODO - add retries. + if (!isOnline()) { + String title = "Cannot upload data"; + String msg = "Please check that you're connected to the Internet"; + //showNotification(title, msg); + send(Message.obtain(null, Medtronic640gActivity.DexcomG4ActivityHandler.MSG_ERROR, title + "\n" + msg)); + } else { + mUploader.execute(cgmRecord); + } } } @@ -225,6 +239,7 @@ public class MedtronicCNLService extends AbstractService { .build()); } + // FIXME - replace this with writing to the SQLite DB. private void writeData(CGMRecord mostRecentData) { //Write most recent data try { diff --git a/app/src/main/java/info/nightscout/android/upload/MedtronicNG/CGMRecord.java b/app/src/main/java/info/nightscout/android/upload/MedtronicNG/CGMRecord.java index 616cbe0c29a46b394559365ea306dea2cb36bb4f..514c7704cdb501cc2be078510d8fdc64f74ac0d0 100644 --- a/app/src/main/java/info/nightscout/android/upload/MedtronicNG/CGMRecord.java +++ b/app/src/main/java/info/nightscout/android/upload/MedtronicNG/CGMRecord.java @@ -30,7 +30,6 @@ public class CGMRecord extends DeviceRecord implements Serializable { private TREND trend = TREND.NOT_SET; - //public Date pumpDate = new Date(); // Store as a date, so we can parse to string later. public int sgv = 0; // in mg/dL. 0 means no sensor reading public Date sgvDate = new Date(); public String direction;