diff --git a/640gAndroidUploader.iml b/640gAndroidUploader.iml deleted file mode 100644 index 21ad486e1dacdc31dfcf484957078ef9fbc29307..0000000000000000000000000000000000000000 --- a/640gAndroidUploader.iml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.id="640gAndroidUploader" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="java-gradle" name="Java-Gradle"> - <configuration> - <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" /> - <option name="BUILDABLE" value="false" /> - </configuration> - </facet> - </component> - <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$"> - <excludeFolder url="file://$MODULE_DIR$/.gradle" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2346e1e45da68fc2d530770a87cd25ad3eea5b02..b5c94546d6e2e01b5d16df7d4f2c716deb630dbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Initial public beta release -[Unreleased]: https://github.com/pazaan/640gAndroidUploader/compare/v0.2.0...HEAD -[v0.2.0]: https://github.com/pazaan/640gAndroidUploader/compare/v0.1.1...v0.2.0 -[v0.1.1]: https://github.com/pazaan/640gAndroidUploader/compare/v0.1.0...v0.1.1 +[Unreleased]: https://github.com/pazaan/600SeriesAndroidUploader/compare/v0.2.0...HEAD +[v0.2.0]: https://github.com/pazaan/600SeriesAndroidUploader/compare/v0.1.1...v0.2.0 +[v0.1.1]: https://github.com/pazaan/600SeriesAndroidUploader/compare/v0.1.0...v0.1.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 24349769999d1fd5bc19e3f775a14f62e682829d..f9eb138370f9fba6133b0f8575defb57d38f71b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ -## How to contribute to 640gAndroidUploader +## How to contribute to 600SeriesAndroidUploader #### **Did you find a bug?** -* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/pazaan/640gAndroidUploader/issues). +* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/pazaan/600SeriesAndroidUploader/issues). -* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/pazaan/640gAndroidUploader/issues/new). Be sure to include a **title and clear description**, and as much relevant information as possible, to help us reproduce the problem on our own gear. +* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/pazaan/600SeriesAndroidUploader/issues/new). Be sure to include a **title and clear description**, and as much relevant information as possible, to help us reproduce the problem on our own gear. #### **Did you write a patch that fixes a bug?** @@ -13,6 +13,6 @@ * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. </br> -640gAndroidUploader is a volunteer effort. We encourage you to pitch in and [join the team](https://gitter.im/pazaan/decoding-contour-next-link) +600SeriesAndroidUploader is a volunteer effort. We encourage you to pitch in and [join the team](https://gitter.im/pazaan/decoding-contour-next-link) Thanks! :heart: :squirrel: :heart: diff --git a/README.md b/README.md index 599ec520263dbf85f894c94c8bc2c130f1d7a9e9..82c9500a436425a1dd728010090afa76c3b7e769 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -[](http://waffle.io/pazaan/640gAndroidUploader) +[](http://waffle.io/pazaan/600SeriesAndroidUploader) -## 640gAndroidUploader +## 600SeriesAndroidUploader -This is an Android app to upload data from a MiniMed 640G insulin pump to a Nightscout website via a Contour Next Link 2.4 blood glucose meter +This is an Android app to upload data from a MiniMed 600 Series insulin pump to a Nightscout website via a Contour Next Link 2.4 blood glucose meter -###### [Click here for more info](https://github.com/pazaan/640gAndroidUploader/wiki) -###### [Click here for Releases](https://github.com/pazaan/640gAndroidUploader/releases) -###### [Click here for the Main Project Page](http://pazaan.github.io/640gAndroidUploader/) +###### [Click here for more info](https://github.com/pazaan/600SeriesAndroidUploader/wiki) +###### [Click here for Releases](https://github.com/pazaan/600SeriesAndroidUploader/releases) +###### [Click here for the Main Project Page](http://pazaan.github.io/600SeriesAndroidUploader/) <br/> -<a target="blank" href="https://raw.githubusercontent.com/wiki/pazaan/640gAndroidUploader/images/kit-showing-app.jpg"><img src="https://raw.githubusercontent.com/wiki/pazaan/640gAndroidUploader/images/kit-showing-app.jpg" width="200"></a> -<a target="blank" href="https://raw.githubusercontent.com/wiki/pazaan/640gAndroidUploader/images/kit-in-case-1.jpg"><img src="https://raw.githubusercontent.com/wiki/pazaan/640gAndroidUploader/images/kit-in-case-1.jpg" width="200"></a> -<a target="blank" href="https://raw.githubusercontent.com/wiki/pazaan/640gAndroidUploader/images/kit-in-case-2.jpg"><img src="https://raw.githubusercontent.com/wiki/pazaan/640gAndroidUploader/images/kit-in-case-2.jpg" width="200"></a> +<a target="blank" href="https://raw.githubusercontent.com/wiki/pazaan/600SeriesAndroidUploader/images/kit-showing-app.jpg"><img src="https://raw.githubusercontent.com/wiki/pazaan/600SeriesAndroidUploader/images/kit-showing-app.jpg" width="200"></a> +<a target="blank" href="https://raw.githubusercontent.com/wiki/pazaan/600SeriesAndroidUploader/images/kit-in-case-1.jpg"><img src="https://raw.githubusercontent.com/wiki/pazaan/600SeriesAndroidUploader/images/kit-in-case-1.jpg" width="200"></a> +<a target="blank" href="https://raw.githubusercontent.com/wiki/pazaan/600SeriesAndroidUploader/images/kit-in-case-2.jpg"><img src="https://raw.githubusercontent.com/wiki/pazaan/600SeriesAndroidUploader/images/kit-in-case-2.jpg" width="200"></a> <br/><br/> #### Development - getting started @@ -25,7 +25,13 @@ This is an Android app to upload data from a MiniMed 640G insulin pump to a Nigh android:value="YOUR-FABRIC-KEY" /> ``` - (**take care not to commit this change**) + (**Please take care not to commit this change. + If you're considering sharing your changes, or are using a non-private + Github repository, you should remove this change in + `app/src/AndroidManifest.xml` and copy the value as `apiKey` property + to file `app/fabric.properties` instead. See + https://docs.fabric.io/android/fabric/settings/working-in-teams.html#android-projects + for more information.**) - Create a [BugFender](https://app.bugfender.com) account, create `app/bugfender.properties` and populate with ``` @@ -36,16 +42,17 @@ This is an Android app to upload data from a MiniMed 640G insulin pump to a Nigh - Use one of the run configurations, eg `installDebug` #### App Credits -* Based on https://github.com/arbox0/MedtronicUploader *(though the internals are completely changed for the 640G)* +* Based on https://github.com/arbox0/MedtronicUploader *(though the internals are completely changed for the 600 Series pumps)* * Uses the [android-service-example](https://code.launchpad.net/~binwiederhier/+junk/android-service-example) by Philipp C. Heckel * Project initiated by [@pazaan](https://github.com/pazaan) <br/> + #### Disclaimer And Warning + All information, thought, and code described here is intended for informational and educational purposes only. Nightscout currently makes no attempt at HIPAA privacy compliance. Use Nightscout at your own risk, and do not use the information or code to make medical decisions. -+ Use of code from github.com is without warranty or formal support of any kind. Please review this repository's [LICENSE](https://github.com/pazaan/640gAndroidUploader/blob/master/LICENSE) for details. ++ Use of code from github.com is without warranty or formal support of any kind. Please review this repository's [LICENSE](https://github.com/pazaan/600SeriesAndroidUploader/blob/master/LICENSE) for details. + All product and company names, trademarks, servicemarks, registered trademarks, and registered servicemarks are the property of their respective holders. Their use is for information purposes and does not imply any affiliation with or endorsement by them. diff --git a/app/640gUploader.iml b/app/640gUploader.iml deleted file mode 100644 index 45575b43f07bf114a0d826ad3cb7d363481e01df..0000000000000000000000000000000000000000 --- a/app/640gUploader.iml +++ /dev/null @@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.id=":640gUploader" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="Medtronic640gUploader" external.system.module.version="unspecified" type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="android-gradle" name="Android-Gradle"> - <configuration> - <option name="GRADLE_PROJECT_PATH" value=":640gUploader" /> - </configuration> - </facet> - <facet type="android" name="Android"> - <configuration> - <option name="SELECTED_BUILD_VARIANT" value="debug" /> - <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" /> - <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" /> - <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" /> - <afterSyncTasks> - <task>generateDebugSources</task> - </afterSyncTasks> - <option name="ALLOW_USER_CONFIGURATION" value="false" /> - <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> - <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> - <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" /> - <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> - </configuration> - </facet> - </component> - <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false"> - <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" /> - <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" /> - <exclude-output /> - <content url="file://$MODULE_DIR$"> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> - <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" /> - <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> - <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" /> - <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/21.0.3/jars" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" /> - <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" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" /> - <excludeFolder url="file://$MODULE_DIR$/build/outputs" /> - <excludeFolder url="file://$MODULE_DIR$/build/tmp" /> - </content> - <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" /> - <orderEntry type="sourceFolder" forTests="false" /> - <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-v4-21.0.3" 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="logback-android-1.1.1-3" level="project" /> - </component> -</module> \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index b54f1f8a56453af8a710861a1fe258c16bf8d0be..be61b980fa21844ef2588710bf0ada5b4d6707bb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,17 +2,18 @@ import org.ajoberstar.grgit.Grgit buildscript { repositories { + jcenter() maven { url 'https://maven.fabric.io/public' } } dependencies { classpath 'io.fabric.tools:gradle:1.21.6' - classpath 'io.realm:realm-gradle-plugin:2.3.1' + classpath 'io.realm:realm-gradle-plugin:3.1.2' classpath 'org.ajoberstar:grgit:1.5.0' } } plugins { - id 'net.researchgate.release' version '2.3.4' + id 'net.researchgate.release' version '2.4.0' } apply plugin: 'com.android.application' @@ -48,15 +49,15 @@ def gitBranch() { return ext.repo.branch.current.name } -def getBugfenderApiKey() { +static def getBugfenderApiKey() { Properties properties = new Properties() properties.load(new FileInputStream("app/bugfender.properties")) return "\"" + properties.getProperty("apiKey", "") + "\"" } android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" + compileSdkVersion 25 + buildToolsVersion '25.0.2' // FIXME - replace with URLConnection. This is used in ManageCNLActivity. useLibrary 'org.apache.http.legacy' @@ -67,7 +68,7 @@ android { defaultConfig { applicationId "info.nightscout.android" minSdkVersion 14 - targetSdkVersion 23 + targetSdkVersion 25 versionName project.properties['version'] + "/" + gitCommitId() // + " (" + gitBranch()+")" versionCode gitVersion() buildConfigField "String", "BUGFENDER_API_KEY", getBugfenderApiKey() @@ -116,11 +117,11 @@ task signRelease << { task zipalignRelease << { def command = [ - '/Users/lennart/Library/Android/sdk/build-tools/23.0.3/zipalign', + '/Users/lennart/Library/Android/sdk/build-tools/25.0.2/zipalign', '-v', '4', 'app/build/outputs/apk/app-release-unsigned.apk', - 'app/build/outputs/apk/640g-android-uploader.apk' + 'app/build/outputs/apk/600-series-uploader.apk' ] def proc = new ProcessBuilder(command) @@ -145,26 +146,30 @@ release { dependencies { compile files('libs/slf4j-api-1.7.2.jar') - compile('com.crashlytics.sdk.android:crashlytics:2.6.7@aar') { - transitive = true; - } - compile('com.mikepenz:materialdrawer:5.2.9@aar') { - transitive = true - } - compile 'com.android.support:appcompat-v7:23.4.0' + + compile 'com.android.support:support-v13:25.3.1' + compile 'com.android.support:design:25.3.1' + compile 'com.android.support:appcompat-v7:25.3.1' + compile 'com.android.support:recyclerview-v7:25.3.1' + compile 'com.android.support:cardview-v7:25.3.1' compile 'org.apache.commons:commons-lang3:3.4' compile 'com.mikepenz:google-material-typeface:2.2.0.1.original@aar' compile 'uk.co.chrisjenx:calligraphy:2.2.0' compile 'com.bugfender.sdk:android:0.7.2' compile 'com.jjoe64:graphview:4.0.1' - compile 'com.android.support:support-v4:23.4.0' 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' - compile 'com.google.android.gms:play-services-appindexing:8.4.0' - + // The version of okhttp3 *must* be the same as the version in AppUpdater + compile 'com.squareup.okhttp3:okhttp:3.6.0' + compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' + compile('com.crashlytics.sdk.android:crashlytics:2.6.7@aar') { + transitive = true; + } + compile('com.mikepenz:materialdrawer:5.2.9@aar') { + transitive = true + } + compile 'com.github.javiersantos:AppUpdater:2.6.1' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 82d30493197be0106b2cf30795d7fed79e1ec57d..3e5115f5ee899354c561c7788101e4fb9bd054ee 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -84,11 +84,6 @@ <receiver android:name=".upload.nightscout.NightscoutUploadReceiver" /> <receiver android:name=".xdrip_plus.XDripPlusUploadReceiver" /> - - <receiver android:name=".medtronic.service.MedtronicCnlAlarmReceiver"></receiver> - - - </application> </manifest> \ No newline at end of file diff --git a/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java b/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java new file mode 100644 index 0000000000000000000000000000000000000000..3924ee0bbf610fd9a72a20c66dc31ca6509cb742 --- /dev/null +++ b/app/src/main/java/com/google/zxing/integration/android/IntentIntegrator.java @@ -0,0 +1,506 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.ActivityNotFoundException; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +/** + * <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple + * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the + * project's source code.</p> + * + * <h2>Initiating a barcode scan</h2> + * + * <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait + * for the result in your app.</p> + * + * <p>It does require that the Barcode Scanner (or work-alike) application is installed. The + * {@link #initiateScan()} method will prompt the user to download the application, if needed.</p> + * + * <p>There are a few steps to using this integration. First, your {@link Activity} must implement + * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p> + * + * <pre>{@code + * public void onActivityResult(int requestCode, int resultCode, Intent intent) { + * IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); + * if (scanResult != null) { + * // handle scan result + * } + * // else continue with any other code you need in the method + * ... + * } + * }</pre> + * + * <p>This is where you will handle a scan result.</p> + * + * <p>Second, just call this in response to a user action somewhere to begin the scan process:</p> + * + * <pre>{@code + * IntentIntegrator integrator = new IntentIntegrator(yourActivity); + * integrator.initiateScan(); + * }</pre> + * + * <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the + * user was prompted to download the application. This lets the calling app potentially manage the dialog. + * In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()} + * method.</p> + * + * <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use + * {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and + * yes/no button labels can be changed.</p> + * + * <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used + * to invoke the scanner. This can be used to set additional options not directly exposed by this + * simplified API.</p> + * + * <p>By default, this will only allow applications that are known to respond to this intent correctly + * do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}. + * For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p> + * + * <h2>Sharing text via barcode</h2> + * + * <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p> + * + * <p>Some code, particularly download integration, was contributed from the Anobiit application.</p> + * + * <h2>Enabling experimental barcode formats</h2> + * + * <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as + * PDF417. Use {@link #initiateScan(Collection)} with + * a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such + * formats.</p> + * + * @author Sean Owen + * @author Fred Lin + * @author Isaac Potoczny-Jones + * @author Brad Drehmer + * @author gcstang + */ +public class IntentIntegrator { + + public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits + private static final String TAG = IntentIntegrator.class.getSimpleName(); + + public static final String DEFAULT_TITLE = "Install Barcode Scanner?"; + public static final String DEFAULT_MESSAGE = + "This application requires Barcode Scanner. Would you like to install it?"; + public static final String DEFAULT_YES = "Yes"; + public static final String DEFAULT_NO = "No"; + + private static final String BS_PACKAGE = "com.google.zxing.client.android"; + private static final String BSPLUS_PACKAGE = "com.srowen.bs.android"; + + // supported barcode formats + public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14"); + public static final Collection<String> ONE_D_CODE_TYPES = + list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128", + "ITF", "RSS_14", "RSS_EXPANDED"); + public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE"); + public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX"); + + public static final Collection<String> ALL_CODE_TYPES = null; + + public static final List<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE); + public static final List<String> TARGET_ALL_KNOWN = list( + BSPLUS_PACKAGE, // Barcode Scanner+ + BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple + BS_PACKAGE // Barcode Scanner + // What else supports this intent? + ); + + private final Activity activity; + private final Fragment fragment; + + private String title; + private String message; + private String buttonYes; + private String buttonNo; + private List<String> targetApplications; + private final Map<String,Object> moreExtras = new HashMap<>(3); + + /** + * @param activity {@link Activity} invoking the integration + */ + public IntentIntegrator(Activity activity) { + this.activity = activity; + this.fragment = null; + initializeConfiguration(); + } + + /** + * @param fragment {@link Fragment} invoking the integration. + * {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead + * of an {@link Activity} + */ + public IntentIntegrator(Fragment fragment) { + this.activity = fragment.getActivity(); + this.fragment = fragment; + initializeConfiguration(); + } + + private void initializeConfiguration() { + title = DEFAULT_TITLE; + message = DEFAULT_MESSAGE; + buttonYes = DEFAULT_YES; + buttonNo = DEFAULT_NO; + targetApplications = TARGET_ALL_KNOWN; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setTitleByID(int titleID) { + title = activity.getString(titleID); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setMessageByID(int messageID) { + message = activity.getString(messageID); + } + + public String getButtonYes() { + return buttonYes; + } + + public void setButtonYes(String buttonYes) { + this.buttonYes = buttonYes; + } + + public void setButtonYesByID(int buttonYesID) { + buttonYes = activity.getString(buttonYesID); + } + + public String getButtonNo() { + return buttonNo; + } + + public void setButtonNo(String buttonNo) { + this.buttonNo = buttonNo; + } + + public void setButtonNoByID(int buttonNoID) { + buttonNo = activity.getString(buttonNoID); + } + + public Collection<String> getTargetApplications() { + return targetApplications; + } + + public final void setTargetApplications(List<String> targetApplications) { + if (targetApplications.isEmpty()) { + throw new IllegalArgumentException("No target applications"); + } + this.targetApplications = targetApplications; + } + + public void setSingleTargetApplication(String targetApplication) { + this.targetApplications = Collections.singletonList(targetApplication); + } + + public Map<String,?> getMoreExtras() { + return moreExtras; + } + + public final void addExtra(String key, Object value) { + moreExtras.put(key, value); + } + + /** + * Initiates a scan for all known barcode types with the default camera. + * + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan() { + return initiateScan(ALL_CODE_TYPES, -1); + } + + /** + * Initiates a scan for all known barcode types with the specified camera. + * + * @param cameraId camera ID of the camera to use. A negative value means "no preference". + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan(int cameraId) { + return initiateScan(ALL_CODE_TYPES, cameraId); + } + + /** + * Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise. + */ + public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) { + return initiateScan(desiredBarcodeFormats, -1); + } + + /** + * Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding + * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants + * like {@link #PRODUCT_CODE_TYPES} for example. + * + * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for + * @param cameraId camera ID of the camera to use. A negative value means "no preference". + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats, int cameraId) { + Intent intentScan = new Intent(BS_PACKAGE + ".SCAN"); + intentScan.addCategory(Intent.CATEGORY_DEFAULT); + + // check which types of codes to scan for + if (desiredBarcodeFormats != null) { + // set the desired barcode types + StringBuilder joinedByComma = new StringBuilder(); + for (String format : desiredBarcodeFormats) { + if (joinedByComma.length() > 0) { + joinedByComma.append(','); + } + joinedByComma.append(format); + } + intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString()); + } + + // check requested camera ID + if (cameraId >= 0) { + intentScan.putExtra("SCAN_CAMERA_ID", cameraId); + } + + String targetAppPackage = findTargetAppPackage(intentScan); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intentScan.setPackage(targetAppPackage); + intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intentScan.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + attachMoreExtras(intentScan); + startActivityForResult(intentScan, REQUEST_CODE); + return null; + } + + /** + * Start an activity. This method is defined to allow different methods of activity starting for + * newer versions of Android and for compatibility library. + * + * @param intent Intent to start. + * @param code Request code for the activity + * @see Activity#startActivityForResult(Intent, int) + * @see Fragment#startActivityForResult(Intent, int) + */ + protected void startActivityForResult(Intent intent, int code) { + if (fragment == null) { + activity.startActivityForResult(intent, code); + } else { + fragment.startActivityForResult(intent, code); + } + } + + private String findTargetAppPackage(Intent intent) { + PackageManager pm = activity.getPackageManager(); + List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (availableApps != null) { + for (String targetApp : targetApplications) { + if (contains(availableApps, targetApp)) { + return targetApp; + } + } + } + return null; + } + + private static boolean contains(Iterable<ResolveInfo> availableApps, String targetApp) { + for (ResolveInfo availableApp : availableApps) { + String packageName = availableApp.activityInfo.packageName; + if (targetApp.equals(packageName)) { + return true; + } + } + return false; + } + + private AlertDialog showDownloadDialog() { + AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); + downloadDialog.setTitle(title); + downloadDialog.setMessage(message); + downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + String packageName; + if (targetApplications.contains(BS_PACKAGE)) { + // Prefer to suggest download of BS if it's anywhere in the list + packageName = BS_PACKAGE; + } else { + // Otherwise, first option: + packageName = targetApplications.get(0); + } + Uri uri = Uri.parse("market://details?id=" + packageName); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + try { + if (fragment == null) { + activity.startActivity(intent); + } else { + fragment.startActivity(intent); + } + } catch (ActivityNotFoundException anfe) { + // Hmm, market is not installed + Log.w(TAG, "Google Play is not installed; cannot install " + packageName); + } + } + }); + downloadDialog.setNegativeButton(buttonNo, null); + downloadDialog.setCancelable(true); + return downloadDialog.show(); + } + + + /** + * <p>Call this from your {@link Activity}'s + * {@link Activity#onActivityResult(int, int, Intent)} method.</p> + * + * @param requestCode request code from {@code onActivityResult()} + * @param resultCode result code from {@code onActivityResult()} + * @param intent {@link Intent} from {@code onActivityResult()} + * @return null if the event handled here was not related to this class, or + * else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning, + * the fields will be null. + */ + public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == REQUEST_CODE) { + if (resultCode == Activity.RESULT_OK) { + String contents = intent.getStringExtra("SCAN_RESULT"); + String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT"); + byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES"); + int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE); + Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation; + String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL"); + return new IntentResult(contents, + formatName, + rawBytes, + orientation, + errorCorrectionLevel); + } + return new IntentResult(); + } + return null; + } + + + /** + * Defaults to type "TEXT_TYPE". + * + * @param text the text string to encode as a barcode + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + * @see #shareText(CharSequence, CharSequence) + */ + public final AlertDialog shareText(CharSequence text) { + return shareText(text, "TEXT_TYPE"); + } + + /** + * Shares the given text by encoding it as a barcode, such that another user can + * scan the text off the screen of the device. + * + * @param text the text string to encode as a barcode + * @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants. + * @return the {@link AlertDialog} that was shown to the user prompting them to download the app + * if a prompt was needed, or null otherwise + */ + public final AlertDialog shareText(CharSequence text, CharSequence type) { + Intent intent = new Intent(); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setAction(BS_PACKAGE + ".ENCODE"); + intent.putExtra("ENCODE_TYPE", type); + intent.putExtra("ENCODE_DATA", text); + String targetAppPackage = findTargetAppPackage(intent); + if (targetAppPackage == null) { + return showDownloadDialog(); + } + intent.setPackage(targetAppPackage); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + attachMoreExtras(intent); + if (fragment == null) { + activity.startActivity(intent); + } else { + fragment.startActivity(intent); + } + return null; + } + + private static List<String> list(String... values) { + return Collections.unmodifiableList(Arrays.asList(values)); + } + + private void attachMoreExtras(Intent intent) { + for (Map.Entry<String,Object> entry : moreExtras.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + // Kind of hacky + if (value instanceof Integer) { + intent.putExtra(key, (Integer) value); + } else if (value instanceof Long) { + intent.putExtra(key, (Long) value); + } else if (value instanceof Boolean) { + intent.putExtra(key, (Boolean) value); + } else if (value instanceof Double) { + intent.putExtra(key, (Double) value); + } else if (value instanceof Float) { + intent.putExtra(key, (Float) value); + } else if (value instanceof Bundle) { + intent.putExtra(key, (Bundle) value); + } else { + intent.putExtra(key, value.toString()); + } + } + } + +} diff --git a/app/src/main/java/com/google/zxing/integration/android/IntentResult.java b/app/src/main/java/com/google/zxing/integration/android/IntentResult.java new file mode 100644 index 0000000000000000000000000000000000000000..15b2e961cdfbb848218261f985dd1edbe76e8ddb --- /dev/null +++ b/app/src/main/java/com/google/zxing/integration/android/IntentResult.java @@ -0,0 +1,93 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.integration.android; + +/** + * <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p> + * + * @author Sean Owen + */ +public final class IntentResult { + + private final String contents; + private final String formatName; + private final byte[] rawBytes; + private final Integer orientation; + private final String errorCorrectionLevel; + + IntentResult() { + this(null, null, null, null, null); + } + + IntentResult(String contents, + String formatName, + byte[] rawBytes, + Integer orientation, + String errorCorrectionLevel) { + this.contents = contents; + this.formatName = formatName; + this.rawBytes = rawBytes; + this.orientation = orientation; + this.errorCorrectionLevel = errorCorrectionLevel; + } + + /** + * @return raw content of barcode + */ + public String getContents() { + return contents; + } + + /** + * @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names. + */ + public String getFormatName() { + return formatName; + } + + /** + * @return raw bytes of the barcode content, if applicable, or null otherwise + */ + public byte[] getRawBytes() { + return rawBytes; + } + + /** + * @return rotation of the image, in degrees, which resulted in a successful scan. May be null. + */ + public Integer getOrientation() { + return orientation; + } + + /** + * @return name of the error correction level used in the barcode, if applicable + */ + public String getErrorCorrectionLevel() { + return errorCorrectionLevel; + } + + @Override + public String toString() { + int rawBytesLength = rawBytes == null ? 0 : rawBytes.length; + return "Format: " + formatName + '\n' + + "Contents: " + contents + '\n' + + "Raw bytes: (" + rawBytesLength + " bytes)\n" + + "Orientation: " + orientation + '\n' + + "EC level: " + errorCorrectionLevel + '\n'; + } + +} 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 a2728bc9a98cc11fd6e2e4b28f4c0744e7ae0cf9..e7cc40393bf3068414137bdc0a67ec824ba70119 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java @@ -29,7 +29,6 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.app.NotificationCompat; import android.support.v7.view.menu.ActionMenuItemView; import android.support.v7.widget.Toolbar; -import android.text.Html; import android.text.format.DateUtils; import android.util.Log; import android.view.Menu; @@ -40,6 +39,8 @@ import android.widget.TextView; import android.widget.TextView.BufferType; import android.widget.Toast; +import com.github.javiersantos.appupdater.AppUpdater; +import com.github.javiersantos.appupdater.enums.UpdateFrom; import com.jjoe64.graphview.DefaultLabelFormatter; import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.Viewport; @@ -74,7 +75,6 @@ import info.nightscout.android.medtronic.service.MedtronicCnlIntentService; import info.nightscout.android.model.medtronicNg.PumpInfo; import info.nightscout.android.model.medtronicNg.PumpStatusEvent; import info.nightscout.android.settings.SettingsActivity; -import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService; import info.nightscout.android.utils.ConfigurationStore; import info.nightscout.android.utils.DataStore; import io.realm.Realm; @@ -99,7 +99,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc private PumpInfo mActivePump; private TextView mTextViewLog; // This will eventually move to a status page. private GraphView mChart; - private Intent mNightscoutUploadService; private Handler mUiRefreshHandler = new Handler(); private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable(); private Realm mRealm; @@ -113,9 +112,9 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc * @return timestamp */ public static long getNextPoll(PumpStatusEvent pumpStatusData) { - long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset(), - now = System.currentTimeMillis(), - pollInterval = ConfigurationStore.getInstance().getPollInterval(); + long nextPoll = pumpStatusData.getSgvDate().getTime() + pumpStatusData.getPumpTimeOffset(), + now = System.currentTimeMillis(), + pollInterval = ConfigurationStore.getInstance().getPollInterval(); // align to next poll slot if (nextPoll + 2 * 60 * 60 * 1000 < now) { // last event more than 2h old -> could be a calibration @@ -137,21 +136,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc return nextPoll; } - public static String strFormatSGV(float sgvValue) { - ConfigurationStore configurationStore = ConfigurationStore.getInstance(); - if (configurationStore.isMmolxl()) { - NumberFormat sgvFormatter; - if (configurationStore.isMmolxlDecimals()) { - sgvFormatter = new DecimalFormat("0.00"); - } else { - sgvFormatter = new DecimalFormat("0.0"); - } - return sgvFormatter.format(sgvValue / MMOLXLFACTOR); - } else { - return String.valueOf(sgvValue); - } - } - @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "onCreate called"); @@ -164,8 +148,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc if (data.size() > 0) dataStore.setLastPumpStatus(data.first()); - mNightscoutUploadService = new Intent(this, NightscoutUploadIntentService.class); - setContentView(R.layout.activity_main); PreferenceManager.getDefaultSharedPreferences(getBaseContext()).registerOnSharedPreferenceChangeListener(this); @@ -257,21 +239,29 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc .withIcon(GoogleMaterial.Icon.gmd_settings) .withSelectable(false); final PrimaryDrawerItem itemRegisterUsb = new PrimaryDrawerItem() - .withName("Registered Devices") + .withName("Registered devices") .withIcon(GoogleMaterial.Icon.gmd_usb) .withSelectable(false); final PrimaryDrawerItem itemStopCollecting = new PrimaryDrawerItem() .withName("Stop collecting data") - .withIcon(GoogleMaterial.Icon.gmd_stop) + .withIcon(GoogleMaterial.Icon.gmd_power_settings_new) .withSelectable(false); final PrimaryDrawerItem itemGetNow = new PrimaryDrawerItem() .withName("Read data now") - .withIcon(GoogleMaterial.Icon.gmd_play_arrow) + .withIcon(GoogleMaterial.Icon.gmd_refresh) + .withSelectable(false); + final PrimaryDrawerItem itemUpdateProfile = new PrimaryDrawerItem() + .withName("Update pump profile") + .withIcon(GoogleMaterial.Icon.gmd_insert_chart) .withSelectable(false); final PrimaryDrawerItem itemClearLog = new PrimaryDrawerItem() - .withName("Clear Log") + .withName("Clear log") .withIcon(GoogleMaterial.Icon.gmd_clear_all) .withSelectable(false); + final PrimaryDrawerItem itemCheckForUpdate = new PrimaryDrawerItem() + .withName("Check for App update") + .withIcon(GoogleMaterial.Icon.gmd_update) + .withSelectable(false); new DrawerBuilder() .withActivity(this) @@ -286,10 +276,12 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc .withSelectedItem(-1) .addDrawerItems( itemSettings, + itemUpdateProfile, itemRegisterUsb, - itemStopCollecting, + itemCheckForUpdate, + itemClearLog, itemGetNow, - itemClearLog + itemStopCollecting ) .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { @Override @@ -307,6 +299,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc startCgmService(0); } else if (drawerItem.equals(itemClearLog)) { clearLogText(); + } else if (drawerItem.equals(itemCheckForUpdate)) { + checkForUpdateNow(); } return false; @@ -355,20 +349,28 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc // due to bug in GraphView v4.2.1 using setNumHorizontalLabels reverted to using v4.0.1 and setHumanRounding is n/a in this version // mChart.getGridLabelRenderer().setHumanRounding(false); - mChart.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() { - DateFormat mFormat = new SimpleDateFormat("HH:mm"); // 24 hour format forced to fix label overlap + mChart.getGridLabelRenderer().setLabelFormatter( + new DefaultLabelFormatter() { + DateFormat mFormat = new SimpleDateFormat("HH:mm", Locale.US); // 24 hour format forced to fix label overlap - @Override - public String formatLabel(double value, boolean isValueX) { - if (isValueX) { - return mFormat.format(new Date((long) value)); - } else { - return sgvFormatter.format(value); + @Override + public String formatLabel(double value, boolean isValueX) { + if (isValueX) { + return mFormat.format(new Date((long) value)); + } else { + return MainActivity.strFormatSGV(value); + } + } } - }} ); } + @Override + protected void onStart() { + super.onStart(); + checkForUpdateBackground(5); + } + @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); @@ -434,7 +436,22 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc private void clearLogText() { statusMessageReceiver.clearMessages(); - //mTextViewLog.setText("", BufferType.EDITABLE); + } + + private void checkForUpdateNow() { + new AppUpdater(this) + .setUpdateFrom(UpdateFrom.JSON) + .setUpdateXML("https://raw.githubusercontent.com/pazaan/600SeriesAndroidUploader/master/app/update.json") + .showAppUpdated(true) // Show a dialog, even if there isn't an update + .start(); + } + + private void checkForUpdateBackground(int checkEvery) { + new AppUpdater(this) + .setUpdateFrom(UpdateFrom.JSON) + .setUpdateXML("https://raw.githubusercontent.com/pazaan/600SeriesAndroidUploader/master/app/update.json") + .showEvery(checkEvery) // Only check for an update every `checkEvery` invocations + .start(); } private void startDisplayRefreshLoop() { @@ -473,10 +490,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc MedtronicCnlAlarmManager.setAlarm(initialPoll); } - private void uploadCgmData() { - startService(mNightscoutUploadService); - } - private void stopCgmService() { Log.i(TAG, "stopCgmService called"); MedtronicCnlAlarmManager.cancelAlarm(); @@ -586,33 +599,12 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc startActivity(manageCNLIntent); } - private String renderTrendHtml(PumpStatusEvent.CGM_TREND trend) { - switch (trend) { - case DOUBLE_UP: - return "⇈"; - case SINGLE_UP: - return "↑"; - case FOURTY_FIVE_UP: - return "↗"; - case FLAT: - return "→"; - case FOURTY_FIVE_DOWN: - return "↘"; - case SINGLE_DOWN: - return "↓"; - case DOUBLE_DOWN: - return "⇊"; - default: - return "—"; - } - } - private PumpInfo getActivePump() { long activePumpMac = dataStore.getActivePumpMac(); if (activePumpMac != 0L && (mActivePump == null || !mActivePump.isValid() || mActivePump.getPumpMac() != activePumpMac)) { if (mActivePump != null) { // remove listener on old pump - mActivePump.removeChangeListeners(); + mActivePump.removeAllChangeListeners(); mActivePump = null; } @@ -625,6 +617,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc mActivePump = pump; mActivePump.addChangeListener(new RealmChangeListener<PumpInfo>() { long lastQueryTS = 0; + @Override public void onChange(PumpInfo pump) { // prevent double updating after deleting old events below @@ -664,42 +657,64 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc return mActivePump; } + + public static String strFormatSGV(double sgvValue) { + ConfigurationStore configurationStore = ConfigurationStore.getInstance(); + + if (configurationStore.isMmolxl()) { + NumberFormat sgvFormatter; + if (configurationStore.isMmolxlDecimals()) { + sgvFormatter = new DecimalFormat("0.00"); + } else { + sgvFormatter = new DecimalFormat("0.0"); + } + return sgvFormatter.format(sgvValue / MMOLXLFACTOR); + } else { + return String.valueOf(sgvValue); + } + } + + public static String renderTrendSymbol(PumpStatusEvent.CGM_TREND trend) { + switch (trend) { + case DOUBLE_UP: + return "\u21c8"; + case SINGLE_UP: + return "\u2191"; + case FOURTY_FIVE_UP: + return "\u2197"; + case FLAT: + return "\u2192"; + case FOURTY_FIVE_DOWN: + return "\u2198"; + case SINGLE_DOWN: + return "\u2193"; + case DOUBLE_DOWN: + return "\u21ca"; + default: + return "\u2014"; + } + } + private class StatusMessageReceiver extends BroadcastReceiver { private class StatusMessage { private long timestamp; private String message; - public StatusMessage(String message) { + StatusMessage(String message) { this(System.currentTimeMillis(), message); } - public StatusMessage(long timestamp, String message) { + StatusMessage(long timestamp, String message) { this.timestamp = timestamp; this.message = message; } - public long getTimestamp() { - return timestamp; - } - - public void setTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - public String toString() { return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(timestamp) + ": " + message; } } - private Queue<StatusMessage> messages = new ArrayBlockingQueue<>(400); + private final Queue<StatusMessage> messages = new ArrayBlockingQueue<>(400); @Override public void onReceive(Context context, Intent intent) { @@ -735,7 +750,6 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc private class RefreshDisplayRunnable implements Runnable { @Override public void run() { - // UI elements - TODO do these need to be members? TextView textViewBg = (TextView) findViewById(R.id.textview_bg); TextView textViewBgTime = (TextView) findViewById(R.id.textview_bg_time); TextView textViewUnits = (TextView) findViewById(R.id.textview_units); @@ -750,31 +764,32 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc // Get the most recently written CGM record for the active pump. PumpStatusEvent pumpStatusData = null; - // ignoring activePump atm - //PumpInfo pump = getActivePump(); - if (dataStore.getLastPumpStatus().getEventDate().getTime() > 0) { pumpStatusData = dataStore.getLastPumpStatus(); } updateChart(mRealm.where(PumpStatusEvent.class) - .greaterThan("eventDate", new Date(System.currentTimeMillis() - 1000*60*60*24)) - .findAllSorted("eventDate", Sort.ASCENDING)); + .greaterThan("sgvDate", new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24)) + .findAllSorted("sgvDate", Sort.ASCENDING)); if (pumpStatusData != null) { String sgvString; - if (configurationStore.isMmolxl()) { - float fBgValue = (float) pumpStatusData.getSgv(); - sgvString = sgvFormatter.format(fBgValue / MMOLXLFACTOR); - Log.d(TAG, sgvString + " mmol/L"); + if (pumpStatusData.isCgmActive()) { + sgvString = MainActivity.strFormatSGV(pumpStatusData.getSgv()); + ; + if (configurationStore.isMmolxl()) { + Log.d(TAG, sgvString + " mmol/L"); + } else { + Log.d(TAG, sgvString + " mg/dL"); + } } else { - sgvString = String.valueOf(pumpStatusData.getSgv()); - Log.d(TAG, sgvString + " mg/dL"); + sgvString = "\u2014"; // — } textViewBg.setText(sgvString); textViewBgTime.setText(DateUtils.getRelativeTimeSpanString(pumpStatusData.getEventDate().getTime())); - textViewTrend.setText(Html.fromHtml(renderTrendHtml(pumpStatusData.getCgmTrend()))); + + textViewTrend.setText(MainActivity.renderTrendSymbol(pumpStatusData.getCgmTrend())); textViewIOB.setText(String.format(Locale.getDefault(), "%.2f", pumpStatusData.getActiveInsulin())); ActionMenuItemView batIcon = ((ActionMenuItemView) findViewById(R.id.status_battery)); @@ -838,18 +853,11 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc } DataPoint[] entries = new DataPoint[size]; - final long left = System.currentTimeMillis() - chartZoom * 60 * 60 * 1000; int pos = 0; - for (PumpStatusEvent pumpStatus: results) { + for (PumpStatusEvent pumpStatus : results) { // turn your data into Entry objects - int sgv = pumpStatus.getSgv(); - - if (configurationStore.isMmolxl()) { - entries[pos++] = new DataPoint(pumpStatus.getEventDate(), (float) pumpStatus.getSgv() / MMOLXLFACTOR); - } else { - entries[pos++] = new DataPoint(pumpStatus.getEventDate(), (float) pumpStatus.getSgv()); - } + entries[pos++] = new DataPoint(pumpStatus.getSgvDate(), (double) pumpStatus.getSgv()); } if (mChart.getSeries().size() == 0) { @@ -874,7 +882,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc double sgv = dataPoint.getY(); StringBuilder sb = new StringBuilder(mFormat.format(new Date((long) dataPoint.getX())) + ": "); - sb.append(sgvFormatter.format(sgv)); + sb.append(MainActivity.strFormatSGV(sgv)); Toast.makeText(getBaseContext(), sb.toString(), Toast.LENGTH_SHORT).show(); } }); @@ -884,11 +892,11 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc public void draw(Canvas canvas, Paint paint, float x, float y, DataPointInterface dataPoint) { double sgv = dataPoint.getY(); boolean mmolxl = configurationStore.isMmolxl(); - if (sgv < (mmolxl?4.5:80)) + if (sgv < (mmolxl ? 4.5 : 80)) paint.setColor(Color.RED); - else if (sgv <= (mmolxl?10:180)) + else if (sgv <= (mmolxl ? 10 : 180)) paint.setColor(Color.GREEN); - else if (sgv <= (mmolxl?14:260)) + else if (sgv <= (mmolxl ? 14 : 260)) paint.setColor(Color.YELLOW); else paint.setColor(Color.RED); @@ -904,7 +912,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc } } - // set vieport to latest SGV + // set viewport to latest SGV long lastSGVTimestamp = (long) mChart.getSeries().get(0).getHighestValueX(); if (!hasZoomedChart) { mChart.getViewport().setMaxX(lastSGVTimestamp); @@ -973,7 +981,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc if (arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_LOW) || arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED) || arg1.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_OKAY)) { - dataStore.setUplooaderBatteryLevel(arg1.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)); + dataStore.setUploaderBatteryLevel(arg1.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)); } } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java b/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java index b995c0d92f014672185beb3e0f4812da02682aaa..78d55479c0627ff3ebf470d7e5e01700bfe6dfe4 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java +++ b/app/src/main/java/info/nightscout/android/medtronic/ManageCNLActivity.java @@ -1,10 +1,8 @@ package info.nightscout.android.medtronic; import android.content.Context; -import android.content.DialogInterface; import android.graphics.Color; import android.os.Bundle; -import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; @@ -57,7 +55,7 @@ public class ManageCNLActivity extends AppCompatActivity { mRealm = Realm.getDefaultInstance(); //generate list - ArrayList<ContourNextLinkInfo> list = new ArrayList<ContourNextLinkInfo>(); + ArrayList<ContourNextLinkInfo> list = new ArrayList<>(); list.addAll(mRealm.where(ContourNextLinkInfo.class).findAll()); @@ -66,9 +64,9 @@ public class ManageCNLActivity extends AppCompatActivity { //handle listview and assign adapter ListView lView = (ListView) findViewById(R.id.cnl_list); - lView.setAdapter(adapter); lView.addHeaderView(getLayoutInflater().inflate(R.layout.manage_cnl_listview_header, null)); lView.setEmptyView(findViewById(R.id.manage_cnl_listview_empty)); //getLayoutInflater().inflate(R.layout.manage_cnl_listview_empty, null)); + lView.setAdapter(adapter); } @Override @@ -123,7 +121,7 @@ public class ManageCNLActivity extends AppCompatActivity { View view = convertView; if (view == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(R.layout.cnl_item, null); + view = inflater.inflate(R.layout.cnl_item, parent, false); } //Handle TextView and display string from your list diff --git a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlSession.java b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlSession.java index a86820f7b72797aa1a2f7c1c19dc5fb6034db430..918e794d9e3388d3c565561f1e9a77af519c38cf 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlSession.java +++ b/app/src/main/java/info/nightscout/android/medtronic/MedtronicCnlSession.java @@ -21,7 +21,7 @@ public class MedtronicCnlSession { private byte radioChannel; private byte radioRSSI; - private int bayerSequenceNumber = 1; + private int cnlSequenceNumber = 1; private int medtronicSequenceNumber = 1; public byte[] getHMAC() throws NoSuchAlgorithmException { @@ -65,8 +65,8 @@ public class MedtronicCnlSession { this.pumpMAC = pumpMAC; } - public int getBayerSequenceNumber() { - return bayerSequenceNumber; + public int getCnlSequenceNumber() { + return cnlSequenceNumber; } public int getMedtronicSequenceNumber() { @@ -85,8 +85,8 @@ public class MedtronicCnlSession { return (((int) radioRSSI & 0x00FF) * 100) / 0xA8; } - public void incrBayerSequenceNumber() { - bayerSequenceNumber++; + public void incrCnlSequenceNumber() { + cnlSequenceNumber++; } public void incrMedtronicSequenceNumber() { diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java index 3902beb03e6e87cdb322871d28fddb1ab80f3a85..7a2d11bb6045345401faefb8eca06641ce6faae7 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/BeginEHSMMessage.java @@ -1,9 +1,5 @@ package info.nightscout.android.medtronic.message; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java index 84dc029782c0306a1f86e70c19b467fc3e7bea11..abf23486fbd627c1bd271301f14584f17a507cb9 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ChannelNegotiateRequestMessage.java @@ -31,9 +31,8 @@ public class ChannelNegotiateRequestMessage extends MedtronicRequestMessage<Chan readMessage(mDevice); // The 0x80 message Log.d(TAG, "negotiateChannel: Reading 0x80 message"); - ChannelNegotiateResponseMessage response = this.getResponse(readMessage(mDevice)); - return response; + return this.getResponse(readMessage(mDevice)); } @Override diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java index 18de1f899ec1354ce7605ccd486c4aaa0bf845d8..bc8aa8a6a5f1850c3c25b6dd128d80d29d1b19a6 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionRequestMessage.java @@ -1,9 +1,7 @@ package info.nightscout.android.medtronic.message; import java.io.IOException; -import java.util.concurrent.TimeoutException; -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java index d1d101e925945018f5b3d87b5a2215acf99cbb14..7f189e33fd89431d2b4bd6c89269fe1b12801698 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/CloseConnectionResponseMessage.java @@ -1,6 +1,5 @@ package info.nightscout.android.medtronic.message; -import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java index 96e72ed8559b0dfbb6d472cc490b7db683dd7a06..fadfec17187f3a7ade746ea7d48473471a8208e8 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkBinaryRequestMessage.java @@ -43,7 +43,7 @@ public abstract class ContourNextLinkBinaryRequestMessage<T> extends ContourNext */ protected void sendMessage(UsbHidDriver mDevice) throws IOException { super.sendMessage(mDevice); - mPumpSession.incrBayerSequenceNumber(); + mPumpSession.incrCnlSequenceNumber(); } protected static byte[] buildPayload(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) { @@ -54,11 +54,11 @@ public abstract class ContourNextLinkBinaryRequestMessage<T> extends ContourNext payloadBuffer.put((byte) 0x51); payloadBuffer.put((byte) 0x3); - payloadBuffer.put("000000".getBytes()); // Text of PumpInfo serial, but 000000 for 640g + payloadBuffer.put("000000".getBytes()); // Text of PumpInfo serial, but 000000 for 600 Series pumps byte[] unknownBytes = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; payloadBuffer.put(unknownBytes); payloadBuffer.put(commandType.getValue()); - payloadBuffer.putInt(pumpSession.getBayerSequenceNumber()); + payloadBuffer.putInt(pumpSession.getCnlSequenceNumber()); byte[] unknownBytes2 = {0, 0, 0, 0, 0}; payloadBuffer.put(unknownBytes2); payloadBuffer.putInt(payloadLength); diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java index 36b7530d61104c8c87bd63a8f604c8a6718874fd..7a948f02fe07a27c2ef6c386ae62a172686a1197 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkCommandMessage.java @@ -1,12 +1,6 @@ package info.nightscout.android.medtronic.message; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.exception.ChecksumException; -import info.nightscout.android.medtronic.exception.EncryptionException; -import info.nightscout.android.medtronic.exception.UnexpectedMessageException; /** * Created by lgoedhart on 26/03/2016. diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java index 8c340cb9ef425cdd34e8bf322e2eef4aaa791926..0cbe120e2b998dd89680d16f0c5087b6f53e5dc8 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkMessage.java @@ -8,7 +8,6 @@ import java.nio.ByteBuffer; import java.util.concurrent.TimeoutException; import info.nightscout.android.USB.UsbHidDriver; -import info.nightscout.android.medtronic.MainActivity; import info.nightscout.android.utils.HexDump; /** @@ -19,7 +18,7 @@ public abstract class ContourNextLinkMessage { private static final int USB_BLOCKSIZE = 64; private static final int READ_TIMEOUT_MS = 15000; //ASTM standard is 15 seconds (note was previously set at 10 seconds) - private static final String BAYER_USB_HEADER = "ABC"; + private static final String USB_HEADER = "ABC"; protected ByteBuffer mPayload; @@ -95,7 +94,7 @@ public abstract class ContourNextLinkMessage { while (message.length > pos) { ByteBuffer outputBuffer = ByteBuffer.allocate(USB_BLOCKSIZE); int sendLength = (pos + 60 > message.length) ? message.length - pos : 60; - outputBuffer.put(BAYER_USB_HEADER.getBytes()); + outputBuffer.put(USB_HEADER.getBytes()); outputBuffer.put((byte) sendLength); outputBuffer.put(message, pos, sendLength); @@ -124,7 +123,7 @@ public abstract class ContourNextLinkMessage { ByteBuffer header = ByteBuffer.allocate(3); header.put(responseBuffer, 0, 3); String headerString = new String(header.array()); - if (!headerString.equals(BAYER_USB_HEADER)) { + if (!headerString.equals(USB_HEADER)) { throw new IOException("Unexpected header received"); } messageSize = responseBuffer[3]; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java index cd25feda28afca655cdb4eb0cc69dad0304e4c58..681bd909cc388bfe2671bd809d7e3f18c0cbfd95 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkRequestMessage.java @@ -36,10 +36,8 @@ public abstract class ContourNextLinkRequestMessage<T> extends ContourNextLinkMe } } - T response = this.getResponse(readMessage(mDevice)); //new ContourNextLinkCommandResponse(); - // FIXME - We need to care what the response message is - wrong MAC and all that - return response; + return this.getResponse(readMessage(mDevice)); } protected abstract <T> T getResponse(byte[] payload) throws ChecksumException, EncryptionException, IOException, UnexpectedMessageException, TimeoutException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java index d20a5613e3345ccdc13a7499852074372490b249..614a2c4f33dba239941183fda7557d21932353b8 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ContourNextLinkResponseMessage.java @@ -1,8 +1,6 @@ package info.nightscout.android.medtronic.message; -import java.io.IOException; import java.util.Locale; -import java.util.concurrent.TimeoutException; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.UnexpectedMessageException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java index 5335d4cf3b5b48fef9231bc060f011026f5f1f8c..bb681200de437f12f126839a11379b2e130b3c3e 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/EndEHSMMessage.java @@ -1,13 +1,8 @@ package info.nightscout.android.medtronic.message; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; -import info.nightscout.android.medtronic.exception.UnexpectedMessageException; /** * Created by lgoedhart on 26/03/2016. diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/MessageUtils.java b/app/src/main/java/info/nightscout/android/medtronic/message/MessageUtils.java index 5b800808e7ab294f9f115f66589d971ac8dffa32..f5a80e07d2fb8bb3263f92683155c82affc48241 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/MessageUtils.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/MessageUtils.java @@ -66,7 +66,6 @@ public class MessageUtils { // However, the time the pump *means* is Fri, 13 May 2016 21:07:48 in our own timezone long offsetFromUTC = currentTz.getOffset(Calendar.getInstance().getTimeInMillis()); - Date pumpDate = new Date((( baseTime + rtc + offset ) * 1000 ) - offsetFromUTC ); - return pumpDate; + return new Date((( baseTime + rtc + offset ) * 1000 ) - offsetFromUTC ); } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java index 85869867aaf3e5ce37ef1a05fdb76880ca04900b..808324743c26b2f71255e00bd48c59b1247356d5 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionRequestMessage.java @@ -1,9 +1,5 @@ package info.nightscout.android.medtronic.message; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java index 1f8e6df122f3efffe51a1a71a2f9a02e28e0407b..d20c421e301c92e6903720b03b51badc367d45d2 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/OpenConnectionResponseMessage.java @@ -1,6 +1,5 @@ package info.nightscout.android.medtronic.message; -import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java index aa71df206607d8ef811415d199576042c063db3b..18be6188ba743957c83cfd328d4e5d5e0e276033 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/PumpBasalPatternRequestMessage.java @@ -1,9 +1,7 @@ package info.nightscout.android.medtronic.message; import java.io.IOException; -import java.util.concurrent.TimeoutException; -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; 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 1d3862bf29250eff2f7b07123e9cf5684657ecf4..6a70ee7ed1b6d3248102202e43f49d88e26bca86 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 @@ -6,7 +6,6 @@ import java.math.BigDecimal; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Date; -import java.util.Locale; import info.nightscout.android.BuildConfig; import info.nightscout.android.medtronic.MedtronicCnlSession; @@ -47,9 +46,6 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa 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 rtc; - private long offset; - protected PumpStatusResponseMessage(MedtronicCnlSession pumpSession, byte[] payload) throws EncryptionException, ChecksumException, UnexpectedMessageException { super(pumpSession, payload); @@ -115,6 +111,8 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa // CGM SGV sgv = (statusBuffer.getShort(0x35) & 0x0000ffff); // In mg/DL. 0 means no CGM reading + long rtc; + long offset; if ((sgv & 0x200) == 0x200) { // Sensor error. Let's reset. FIXME - solve this more elegantly later sgv = 0; @@ -128,7 +126,6 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa } // SGV Date - // TODO - this should go in the sgvDate, and eventDate should be the time of this poll. sgvDate = MessageUtils.decodeDateTime(rtc, offset); Log.d(TAG, "original sgv date: " + sgvDate); @@ -184,13 +181,10 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa // Active insulin pumpRecord.setActiveInsulin(activeInsulin); - // CGM SGV + // CGM SGV data pumpRecord.setSgv(sgv); pumpRecord.setSgvDate(new Date(sgvDate.getTime() - pumpRecord.getPumpTimeOffset())); - - // SGV Date pumpRecord.setCgmTrend(cgmTrend); - pumpRecord.setEventDate(new Date(sgvDate.getTime() - pumpRecord.getPumpTimeOffset())); // Predictive low suspend // TODO - there is more status info in this byte other than just a boolean yes/no @@ -198,8 +192,11 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa // Recent Bolus Wizard BGL pumpRecord.setRecentBolusWizard(recentBolusWizard); - if (recentBolusWizard && activeInsulin > DataStore.getInstance().getLastPumpStatus().getActiveInsulin()) { // there is a BolusWizard usage & the IOB increaseed + // there is a BolusWizard usage & the IOB increased + if (activeInsulin > DataStore.getInstance().getLastPumpStatus().getActiveInsulin()) { pumpRecord.setBolusWizardBGL(bolusWizardBGL); // In mg/DL + } else { + pumpRecord.setBolusWizardBGL(0); // In mg/DL } } } diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java index ff7a2f692eee0d339f577e30c8059d84d5421dcf..c64ba271f7cf9b10a53fa5f125f980b0b062423a 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadHistoryInfoRequestMessage.java @@ -1,9 +1,7 @@ package info.nightscout.android.medtronic.message; import java.io.IOException; -import java.util.concurrent.TimeoutException; -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java index c357cd5f25ac84be95988ea702987df8ed059deb..01c63ce23d0263e2ba3ff4ed30f313eb441362ea 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/ReadInfoRequestMessage.java @@ -1,9 +1,7 @@ package info.nightscout.android.medtronic.message; import java.io.IOException; -import java.util.concurrent.TimeoutException; -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java index bc2d01869d3c7a47d2080d03bd134837d74fc618..1814fe87fa8df4322fdeead228477434986ca466 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java +++ b/app/src/main/java/info/nightscout/android/medtronic/message/RequestLinkKeyRequestMessage.java @@ -1,9 +1,5 @@ package info.nightscout.android.medtronic.message; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import info.nightscout.android.USB.UsbHidDriver; import info.nightscout.android.medtronic.MedtronicCnlSession; import info.nightscout.android.medtronic.exception.ChecksumException; import info.nightscout.android.medtronic.exception.EncryptionException; diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java index b4f2e153000ada1bbf5932ecbf321dcaa6e5bd57..358cc203123e64d456f05c97cd116eb33e3af9a2 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java +++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmManager.java @@ -5,12 +5,10 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; -import android.support.v4.content.WakefulBroadcastReceiver; import android.util.Log; import java.util.Date; -import info.nightscout.android.medtronic.MainActivity; import info.nightscout.android.utils.ConfigurationStore; /** diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java index d86076cc3f01cf4a433bb3a9cd29196707bbe0c8..ad908713062d88a4c902ab0f933e69354ffd88fe 100644 --- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java +++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlAlarmReceiver.java @@ -1,20 +1,12 @@ package info.nightscout.android.medtronic.service; -import android.app.Activity; -import android.app.AlarmManager; -import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Build; -import android.preference.PreferenceManager; import android.support.v4.content.WakefulBroadcastReceiver; import android.util.Log; import java.util.Date; -import info.nightscout.android.medtronic.MainActivity; - /** * Created by lgoedhart on 14/07/2016. */ 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 79f306e7732a8d8fe46a93c1684fc53b65ce37ee..7dae03154d2797253ca8918c8f8512fd160646e8 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 @@ -138,7 +138,7 @@ public class MedtronicCnlIntentService extends IntentService { UsbDevice cnlStick = UsbHidDriver.getUsbDevice(mUsbManager, USB_VID, USB_PID); if (cnlStick == null) { - sendStatus("USB connection error. Is the Bayer Contour Next Link plugged in?"); + sendStatus("USB connection error. Is the Contour Next Link plugged in?"); Log.w(TAG, "USB connection error. Is the CNL plugged in?"); // TODO - set status if offline or Nightscout not reachable @@ -165,7 +165,7 @@ public class MedtronicCnlIntentService extends IntentService { return; } - DateFormat df = new SimpleDateFormat("HH:mm:ss"); + DateFormat df = new SimpleDateFormat("HH:mm:ss", Locale.US); MedtronicCnlReader cnlReader = new MedtronicCnlReader(mHidDevice); @@ -223,9 +223,9 @@ public class MedtronicCnlIntentService extends IntentService { byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel()); if (radioChannel == 0) { - sendStatus("Could not communicate with the 640g. Are you near the pump?"); - Log.i(TAG, "Could not communicate with the 640g. Are you near the pump?"); - pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway()?2L:1L); // reduce polling interval to half until pump is available + sendStatus("Could not communicate with the pump. Is it nearby?"); + Log.i(TAG, "Could not communicate with the pump. Is it nearby?"); + pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); // reduce polling interval to half until pump is available } else { dataStore.setActivePumpMac(pumpMAC); @@ -236,7 +236,7 @@ public class MedtronicCnlIntentService extends IntentService { // read pump status PumpStatusEvent pumpRecord = realm.createObject(PumpStatusEvent.class); - String deviceName = String.format("medtronic-640g://%s", cnlReader.getStickSerial()); + String deviceName = String.format("medtronic-600://%s", cnlReader.getStickSerial()); activePump.setDeviceName(deviceName); // TODO - this should not be necessary. We should reverse lookup the device name from PumpInfo @@ -258,9 +258,14 @@ public class MedtronicCnlIntentService extends IntentService { } sendStatus("SGV: " + MainActivity.strFormatSGV(pumpRecord.getSgv()) + " At: " + df.format(pumpRecord.getEventDate().getTime()) + " Pump: " + offsetSign + (pumpOffset / 1000L) + "sec"); //note: event time is currently stored with offset - // Check if pump sent old event when new expected - if (((pumpRecord.getEventDate().getTime() - dataStore.getLastPumpStatus().getEventDate().getTime()) < 5000L) && ((timePollExpected - timePollStarted) < 5000L)) { - sendStatus("Pump sent old SGV event"); + // Check if pump sent old event when new expected and schedule a re-poll + if (pumpRecord != null && + dataStore.getLastPumpStatus() != null && + dataStore.getLastPumpStatus().getPumpDate() != null && + ((pumpRecord.getPumpDate().getTime() - dataStore.getLastPumpStatus().getPumpDate().getTime()) < 5000L) && + ((timePollExpected - timePollStarted) < 5000L)) { + pollInterval = 90000L; // polling interval set to 90 seconds + sendStatus("Pump sent old SGV event, re-polling..."); } //MainActivity.timeLastGoodSGV = pumpRecord.getEventDate().getTime(); // track last good sgv event time @@ -294,11 +299,11 @@ public class MedtronicCnlIntentService extends IntentService { } catch (UnexpectedMessageException e) { Log.e(TAG, "Unexpected Message", e); sendStatus("Communication Error: " + e.getMessage()); - pollInterval = 60000L; // retry once during this poll period + pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); } catch (TimeoutException e) { Log.e(TAG, "Timeout communicating with the Contour Next Link.", e); sendStatus("Timeout communicating with the Contour Next Link."); - pollInterval = 60000L; // retry once during this poll period + pollInterval = configurationStore.getPollInterval() / (configurationStore.isReducePollOnPumpAway() ? 2L : 1L); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "Could not determine CNL HMAC", e); sendStatus("Error connecting to Contour Next Link: Hashing error."); @@ -307,7 +312,8 @@ public class MedtronicCnlIntentService extends IntentService { cnlReader.closeConnection(); cnlReader.endPassthroughMode(); cnlReader.endControlMode(); - } catch (NoSuchAlgorithmException e) {} + } catch (NoSuchAlgorithmException e) { + } } } catch (IOException e) { @@ -352,9 +358,8 @@ public class MedtronicCnlIntentService extends IntentService { if (dataStore.getUnavailableSGVCount() > 0) { if (timeLastGoodSGV == 0) { nextRequestedPollTime += POLL_PERIOD_MS / 5L; // if there is a uploader/sensor poll clash on startup then this will push the next attempt out by 60 seconds - } - else if (dataStore.getUnavailableSGVCount() > 2) { - sendStatus("Warning: No SGV available from pump for " +dataStore.getUnavailableSGVCount() + " attempts"); + } else if (dataStore.getUnavailableSGVCount() > 2) { + sendStatus("Warning: No SGV available from pump for " + dataStore.getUnavailableSGVCount() + " attempts"); nextRequestedPollTime += ((long) ((dataStore.getUnavailableSGVCount() - 2) % 5)) * (POLL_PERIOD_MS / 10L); // adjust poll time in 1/10 steps to avoid potential poll clash (max adjustment at 5/10) } } @@ -402,7 +407,6 @@ public class MedtronicCnlIntentService extends IntentService { public static final String ACTION_STATUS_MESSAGE = "info.nightscout.android.medtronic.service.STATUS_MESSAGE"; public static final String ACTION_NO_USB_PERMISSION = "info.nightscout.android.medtronic.service.NO_USB_PERMISSION"; public static final String ACTION_USB_PERMISSION = "info.nightscout.android.medtronic.USB_PERMISSION"; - public static final String ACTION_REFRESH_DATA = "info.nightscout.android.medtronic.service.CGM_DATA"; public static final String ACTION_USB_REGISTER = "info.nightscout.android.medtronic.USB_REGISTER"; public static final String ACTION_UPDATE_PUMP = "info.nightscout.android.medtronic.UPDATE_PUMP"; 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 87adfa0667c404458262d91ce4f503e29dc9e0a1..fdc460fc15c0c491269d82f633bb1daa86a11862 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 @@ -1,7 +1,10 @@ package info.nightscout.android.model.medtronicNg; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.Date; +import info.nightscout.android.utils.ConfigurationStore; import io.realm.RealmObject; import io.realm.annotations.Ignore; import io.realm.annotations.Index; @@ -9,7 +12,7 @@ import io.realm.annotations.Index; /** * Created by lgoedhart on 4/06/2016. */ -public class PumpStatusEvent extends RealmObject { +public class PumpStatusEvent extends RealmObject { @Index 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 @@ -45,13 +48,16 @@ public class PumpStatusEvent extends RealmObject { @Index private boolean uploaded = false; + public PumpStatusEvent() { + // The the eventDate to now. + this.eventDate = new Date(); + } + public Date getEventDate() { return eventDate; } - public void setEventDate(Date eventDate) { - this.eventDate = eventDate; - } + // No EventDate setter. The eventDate is set at the time that the PumpStatusEvent is created. public Date getPumpDate() { return pumpDate; @@ -78,7 +84,15 @@ public class PumpStatusEvent extends RealmObject { } public CGM_TREND getCgmTrend() { - return CGM_TREND.valueOf(cgmTrend); + if (cgmTrend == null || !this.isCgmActive()) { + return CGM_TREND.NOT_SET; + } else { + return CGM_TREND.valueOf(cgmTrend); + } + } + + public void setCgmTrend(String cgmTrend) { + this.cgmTrend = cgmTrend; } public String getCgmTrendString() { @@ -92,10 +106,6 @@ public class PumpStatusEvent extends RealmObject { this.cgmTrend = CGM_TREND.NOT_SET.name(); } - public void setCgmTrend(String cgmTrend) { - this.cgmTrend = cgmTrend; - } - public float getActiveInsulin() { return activeInsulin; } @@ -268,6 +278,38 @@ public class PumpStatusEvent extends RealmObject { this.pumpTimeOffset = pumpTimeOffset; } + @Override + public String toString() { + return "PumpStatusEvent{" + + "eventDate=" + eventDate + + ", pumpDate=" + pumpDate + + ", deviceName='" + deviceName + '\'' + + ", suspended=" + suspended + + ", bolusing=" + bolusing + + ", deliveringInsulin=" + deliveringInsulin + + ", tempBasalActive=" + tempBasalActive + + ", cgmActive=" + cgmActive + + ", activeBasalPattern=" + activeBasalPattern + + ", basalRate=" + basalRate + + ", tempBasalRate=" + tempBasalRate + + ", tempBasalPercentage=" + tempBasalPercentage + + ", tempBasalMinutesRemaining=" + tempBasalMinutesRemaining + + ", basalUnitsDeliveredToday=" + basalUnitsDeliveredToday + + ", batteryPercentage=" + batteryPercentage + + ", reservoirAmount=" + reservoirAmount + + ", minutesOfInsulinRemaining=" + minutesOfInsulinRemaining + + ", activeInsulin=" + activeInsulin + + ", sgv=" + sgv + + ", sgvDate=" + sgvDate + + ", lowSuspendActive=" + lowSuspendActive + + ", cgmTrend='" + cgmTrend + '\'' + + ", recentBolusWizard=" + recentBolusWizard + + ", bolusWizardBGL=" + bolusWizardBGL + + ", pumpTimeOffset=" + pumpTimeOffset + + ", uploaded=" + uploaded + + '}'; + } + public enum CGM_TREND { NONE, DOUBLE_UP, diff --git a/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java b/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java index cbabb6a4ec7e9a497f487642f0fd8f1f06ccf3da..b42a10614fb9f13c13dc06e9d87fb1459bfd166e 100644 --- a/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java +++ b/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java @@ -1,5 +1,6 @@ package info.nightscout.android.settings; +import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; @@ -9,14 +10,25 @@ import android.preference.MultiSelectListPreference; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; +import android.util.Log; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + +import java.net.MalformedURLException; +import java.net.URL; import info.nightscout.android.R; public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener { + private static final String TAG = SettingsFragment.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + final SettingsFragment that = this; /* set preferences */ addPreferencesFromResource(R.xml.preferences); @@ -27,13 +39,23 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref } setMinBatPollIntervall((ListPreference) findPreference("pollInterval"), (ListPreference) findPreference("lowBatPollInterval")); + + Preference button = findPreference("scanButton"); + button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + IntentIntegrator integrator = new IntentIntegrator(that); + integrator.initiateScan(); + + return true; + } + }); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Preference pref = findPreference(key); - if ("pollInterval".equals(key)) { setMinBatPollIntervall((ListPreference) pref, (ListPreference) findPreference("lowBatPollInterval")); } @@ -110,4 +132,55 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref p.setSummary(editTextPref.getText()); } } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + if (requestCode==IntentIntegrator.REQUEST_CODE) + { + IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); + if (scanResult != null) + { + Log.d(TAG, "scanResult returns: " + scanResult.toString()); + + JsonParser json = new JsonParser(); + String resultContents = scanResult.getContents() == null ? "" : scanResult.getContents(); + JsonElement jsonElement = json.parse(resultContents); + if (jsonElement != null && jsonElement.isJsonObject()) { + jsonElement = (jsonElement.getAsJsonObject()).get("rest"); + if (jsonElement != null && jsonElement.isJsonObject()) { + jsonElement = (jsonElement.getAsJsonObject()).get("endpoint"); + if (jsonElement != null && jsonElement.isJsonArray() && jsonElement.getAsJsonArray().size() > 0) { + String endpoint = jsonElement.getAsJsonArray().get(0).getAsString(); + Log.d(TAG, "endpoint: " + endpoint); + + try { + URL uri = new URL(endpoint); + + StringBuilder url = new StringBuilder(uri.getProtocol()) + .append("://").append(uri.getHost()); + if (uri.getPort() > -1) + url.append(":").append(uri.getPort()); + + EditTextPreference editPref = (EditTextPreference) findPreference(getString(R.string.preference_nightscout_url)); + editPref.setText(url.toString()); + updatePrefSummary(editPref); + + editPref = (EditTextPreference) findPreference(getString(R.string.preference_api_secret)); + editPref.setText(uri.getUserInfo()); + updatePrefSummary(editPref); + } catch (MalformedURLException e) { + Log.w (TAG, e.getMessage()); + } + + } + } + } + } + else + { + Log.d(TAG, "scanResult is null."); + } + } + } } \ No newline at end of file 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 4fe14f2a8542bba2bbd0d346a6faf3663204e003..f29c2b894784635831a530b7f8d8bc7b030e95c6 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 @@ -29,7 +29,6 @@ import info.nightscout.api.DeviceEndpoints.PumpInfo; import info.nightscout.api.DeviceEndpoints.DeviceStatus; import okhttp3.ResponseBody; import retrofit2.Response; -import retrofit2.Retrofit; class NightScoutUpload { 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 74afe684f6bbaf431df34c31dd4d08009968bf25..038218934c13ccb0c2e99389977a5106ec8b536a 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 @@ -21,7 +21,6 @@ public class NightscoutUploadIntentService extends IntentService { private static final String TAG = NightscoutUploadIntentService.class.getSimpleName(); private Context mContext; - private Realm mRealm; private NightScoutUpload mNightScoutUpload; public NightscoutUploadIntentService() { @@ -49,7 +48,7 @@ public class NightscoutUploadIntentService extends IntentService { @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent called"); - mRealm = Realm.getDefaultInstance(); + Realm mRealm = Realm.getDefaultInstance(); RealmResults<PumpStatusEvent> records = mRealm .where(PumpStatusEvent.class) @@ -68,7 +67,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().getUplooaderBatteryLevel(), records); + secretSetting, DataStore.getInstance().getUploaderBatteryLevel(), records); if (uploadSuccess) { mRealm.beginTransaction(); for (PumpStatusEvent updateRecord : records) { diff --git a/app/src/main/java/info/nightscout/android/utils/ConfigurationStore.java b/app/src/main/java/info/nightscout/android/utils/ConfigurationStore.java index 1a4fca0c7c7a15b5e96607ed2f56ea389702c501..a45c63f40b50e8771371de624cb05ffc7e8dabd5 100644 --- a/app/src/main/java/info/nightscout/android/utils/ConfigurationStore.java +++ b/app/src/main/java/info/nightscout/android/utils/ConfigurationStore.java @@ -2,7 +2,6 @@ package info.nightscout.android.utils; import info.nightscout.android.medtronic.service.MedtronicCnlIntentService; -import info.nightscout.android.model.medtronicNg.PumpStatusEvent; /** * Created by volker on 30.03.2017. 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 a61fbf7d5ce8e2dc4c239b68da806647512b4bbf..fbd2a02011f40323c64f1b6cf977c59869555a3b 100644 --- a/app/src/main/java/info/nightscout/android/utils/DataStore.java +++ b/app/src/main/java/info/nightscout/android/utils/DataStore.java @@ -1,8 +1,6 @@ package info.nightscout.android.utils; -import com.bugfender.sdk.a.a.k.a; - import java.util.Date; import info.nightscout.android.model.medtronicNg.PumpStatusEvent; @@ -16,7 +14,7 @@ public class DataStore { private static DataStore instance; private PumpStatusEvent lastPumpStatus; - private int uplooaderBatteryLevel = 0; + private int uploaderBatteryLevel = 0; private int unavailableSGVCount = 0; private long activePumpMac = 0; @@ -28,7 +26,6 @@ public class DataStore { // set some initial dummy values PumpStatusEvent dummyStatus = new PumpStatusEvent(); - dummyStatus.setEventDate(new Date(0)); // bypass setter to avoid dealing with a real Realm object instance.lastPumpStatus = dummyStatus; @@ -48,12 +45,12 @@ public class DataStore { if (!realm.isClosed()) realm.close(); } - public int getUplooaderBatteryLevel() { - return uplooaderBatteryLevel; + public int getUploaderBatteryLevel() { + return uploaderBatteryLevel; } - public void setUplooaderBatteryLevel(int uplooaderBatteryLevel) { - this.uplooaderBatteryLevel = uplooaderBatteryLevel; + public void setUploaderBatteryLevel(int uploaderBatteryLevel) { + this.uploaderBatteryLevel = uploaderBatteryLevel; } public int getUnavailableSGVCount() { diff --git a/app/src/main/java/info/nightscout/android/utils/HexDump.java b/app/src/main/java/info/nightscout/android/utils/HexDump.java index ff441ced24ba8bc11f04cc1a57f7ec99a032302a..002ab6b2b69f925b9ba39a44288991bc6416fc10 100644 --- a/app/src/main/java/info/nightscout/android/utils/HexDump.java +++ b/app/src/main/java/info/nightscout/android/utils/HexDump.java @@ -37,7 +37,9 @@ public class HexDump { result.append("\n "); for (int i = 0; i < Math.min(16, array.length); i++) { - result.append(" ?" + HEX_DIGITS[i]); + result + .append(" ?") + .append(HEX_DIGITS[i]); } result.append("\n0x"); @@ -105,6 +107,7 @@ public class HexDump { return new String(buf); } + public static String toHexString(int i) { return toHexString(toByteArray(i)); } @@ -140,8 +143,8 @@ public class HexDump { public static byte[] hexStringToByteArray(String hexString) { int length = hexString.length(); byte[] buffer = new byte[length / 2]; - if (length% 2 == 1) - length--; + if (length % 2 == 1) + length--; for (int i = 0; i < length; i += 2) { buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString .charAt(i + 1))); @@ -149,36 +152,39 @@ public class HexDump { return buffer; } - - public static int unsignedByte(byte b){ - return (b & 0xFF); + + public static int unsignedByte(byte b) { + return (b & 0xFF); } - - public static byte bUnsignedByte(byte b){ - return (byte)(b & 0xFF); + + public static byte bUnsignedByte(byte b) { + return (byte) (b & 0xFF); } + + @SuppressWarnings("ResultOfMethodCallIgnored") public static boolean isHexaNumber(String cadena) { try { - Long.parseLong(cadena,16); + Long.parseLong(cadena, 16); return true; } catch (NumberFormatException nfe) { return false; } } - - public static int byteArrayToInt (byte[] arr){ - int length = arr.length; - int mult = 1; - int res = 0; - if (length > 0 && length <5){ - for (int i = length-1; i >= 0; i--){ - res += unsignedByte(arr[i])*mult; - mult *=256; - } - } - return res; + + public static int byteArrayToInt(byte[] arr) { + int length = arr.length; + int mult = 1; + int res = 0; + if (length > 0 && length < 5) { + for (int i = length - 1; i >= 0; i--) { + res += unsignedByte(arr[i]) * mult; + mult *= 256; + } + } + return res; } - public static short byteArrayToShort (byte[] arr){ - return (short) (unsignedByte(arr[0])*256 + unsignedByte(arr[1])); + + public static short byteArrayToShort(byte[] arr) { + return (short) (unsignedByte(arr[0]) * 256 + unsignedByte(arr[1])); } } 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 d27f95ecf8f02b258b2e06564eb191ad8c8d70e6..20a1183a83ecbae9432f0c048d5088a29f9ba8d5 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 @@ -33,7 +33,6 @@ public class XDripPlusUploadIntentService extends IntentService { private static final String TAG = XDripPlusUploadIntentService.class.getSimpleName(); private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault()); Context mContext; - private Realm mRealm; public XDripPlusUploadIntentService() { super(XDripPlusUploadIntentService.class.getName()); @@ -58,7 +57,7 @@ public class XDripPlusUploadIntentService extends IntentService { @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent called"); - mRealm = Realm.getDefaultInstance(); + Realm mRealm = Realm.getDefaultInstance(); RealmResults<PumpStatusEvent> all_records = mRealm .where(PumpStatusEvent.class) @@ -116,7 +115,7 @@ public class XDripPlusUploadIntentService extends IntentService { private void addDeviceStatus(JSONArray devicestatusArray, PumpStatusEvent record) throws Exception { JSONObject json = new JSONObject(); - json.put("uploaderBattery", DataStore.getInstance().getUplooaderBatteryLevel()); + json.put("uploaderBattery", DataStore.getInstance().getUploaderBatteryLevel()); json.put("device", record.getDeviceName()); json.put("created_at", ISO8601_DATE_FORMAT.format(record.getPumpDate())); diff --git a/app/src/main/java/info/nightscout/api/DeviceEndpoints.java b/app/src/main/java/info/nightscout/api/DeviceEndpoints.java index 1bf66b24336e790d69c464ed1acb419c029d433d..f528c75f14698284d48e3cb0c5bc811ee6817ad6 100644 --- a/app/src/main/java/info/nightscout/api/DeviceEndpoints.java +++ b/app/src/main/java/info/nightscout/api/DeviceEndpoints.java @@ -6,7 +6,6 @@ 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; diff --git a/app/src/main/java/info/nightscout/api/UploadApi.java b/app/src/main/java/info/nightscout/api/UploadApi.java index 165203fc7f6f8101b78dc9130f0f5447d5e10f9c..a2c4a1a322a6c897c2e49b40b52f1ab52ee536a5 100644 --- a/app/src/main/java/info/nightscout/api/UploadApi.java +++ b/app/src/main/java/info/nightscout/api/UploadApi.java @@ -51,7 +51,7 @@ public class UploadApi { Request request = requestBuilder.build(); return chain.proceed(request); } - }; + } OkHttpClient.Builder okHttpClient = new OkHttpClient().newBuilder() .connectTimeout(30, TimeUnit.SECONDS) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 3dfa26586c1b258eca12ab5d0ba8e3f142d02d82..8ed60ee8ad7a7e990026009f04a83bc022016cc3 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -52,8 +52,9 @@ android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="1" - android:singleLine="true" + android:maxLines="1" android:text="-" + android:textAlignment="center" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="70sp" /> @@ -70,7 +71,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center|top" - android:singleLine="true" + android:maxLines="1" android:text="-" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="40sp" /> @@ -80,9 +81,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" - android:singleLine="true" android:text="mmol/L" - android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" + android:maxLines="1" /> </LinearLayout> @@ -128,7 +129,6 @@ android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="fill_parent"> - android:gravity="bottom" <LinearLayout android:orientation="vertical" diff --git a/app/src/main/res/layout/activity_status.xml b/app/src/main/res/layout/activity_status.xml index 5a7529d14946eef094b6b350374771d6c953c670..f67e0965164757e5c4131440ac5a5a3478909546 100644 --- a/app/src/main/res/layout/activity_status.xml +++ b/app/src/main/res/layout/activity_status.xml @@ -26,40 +26,172 @@ </android.support.design.widget.AppBarLayout> <ScrollView + android:id="@+id/status_scroll_view" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:id="@+id/status_scroll_view" + android:layout_marginLeft="@dimen/activity_horizontal_margin" + android:layout_marginRight="@dimen/activity_horizontal_margin" android:fillViewport="true"> <LinearLayout - android:orientation="vertical" + android:id="@+id/x" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:layout_margin="5dp" + android:orientation="vertical"> <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Pump Status" android:id="@+id/status_pump_text_view" - android:singleLine="true" /> + style="?android:attr/listSeparatorTextViewStyle" + android:layout_height="wrap_content" + android:maxLines="1" + android:text="Pump Status" /> + + <GridLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <android.support.v7.widget.CardView + android:id="@+id/card_view" + android:layout_width="100dp" + android:layout_height="100dp" + android:layout_gravity="center" + app:cardCornerRadius="4dp"> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="5dp"> + + <ImageView + android:id="@+id/imageView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:scaleType="center" + app:srcCompat="@drawable/battery_0" /> + + <TextView + android:id="@+id/textView2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/textView" + android:text="Units Remaining" + android:textAppearance="@style/TextAppearance.AppCompat.Caption" /> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/imageView" + android:layout_centerHorizontal="true" + android:layout_centerInParent="true" + android:text="150.250" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.AppCompat.Headline" /> + </RelativeLayout> + + </android.support.v7.widget.CardView> + + <android.support.v7.widget.CardView + android:id="@+id/card_view" + android:layout_width="100dp" + android:layout_height="100dp" + android:layout_gravity="center" + app:cardCornerRadius="4dp"> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="5dp"> + + <ImageView + android:id="@+id/imageView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:scaleType="center" + app:srcCompat="@drawable/battery_0" /> + + <TextView + android:id="@+id/textView2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/textView" + android:text="Units Remaining" + android:textAppearance="@style/TextAppearance.AppCompat.Caption" /> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/imageView" + android:layout_centerHorizontal="true" + android:layout_centerInParent="true" + android:text="150.250" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.AppCompat.Headline" /> + </RelativeLayout> + + </android.support.v7.widget.CardView> + + <android.support.v7.widget.CardView + android:id="@+id/card_view" + android:layout_width="100dp" + android:layout_height="100dp" + android:layout_gravity="center" + app:cardCornerRadius="4dp"> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="5dp"> + + <ImageView + android:id="@+id/imageView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:scaleType="center" + app:srcCompat="@drawable/battery_0" /> + + <TextView + android:id="@+id/textView2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/textView" + android:text="Units Remaining" + android:textAppearance="@style/TextAppearance.AppCompat.Caption" /> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/imageView" + android:layout_centerHorizontal="true" + android:layout_centerInParent="true" + android:text="150.250" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.AppCompat.Headline" /> + </RelativeLayout> + + </android.support.v7.widget.CardView> + </GridLayout> <TextView - android:layout_width="wrap_content" + android:id="@+id/status_uploader_text_view" + style="?android:attr/listSeparatorTextViewStyle" android:layout_height="wrap_content" - android:text="Uploader Status" - android:id="@+id/status_uploader_text_view" /> + android:text="Uploader Status" /> <TextView - android:layout_width="wrap_content" + android:id="@+id/status_cgm_text_view" + style="?android:attr/listSeparatorTextViewStyle" android:layout_height="wrap_content" - android:text="CGM Status" - android:id="@+id/status_cgm_text_view" /> + android:text="CGM Status" /> <TextView - android:layout_width="wrap_content" + android:id="@+id/status_nightscout_text_view" + style="?android:attr/listSeparatorTextViewStyle" android:layout_height="wrap_content" - android:text="Nightscout Status" - android:id="@+id/status_nightscout_text_view" /> + android:text="Nightscout Status" /> </LinearLayout> </ScrollView> diff --git a/app/src/main/res/layout/cnl_item.xml b/app/src/main/res/layout/cnl_item.xml index 5ce73b2c268c0bfb9e233f7504435b64cc1c06d1..2fb909e0027846c2b164a33e14ba004a6785bf10 100644 --- a/app/src/main/res/layout/cnl_item.xml +++ b/app/src/main/res/layout/cnl_item.xml @@ -10,6 +10,7 @@ android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:paddingLeft="8dp" + android:paddingRight="8dp" android:textSize="18sp" android:textStyle="bold" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b403419f414cf3f94125d7f47ae87e0e7f14e5b7..00a38b6e1b8665f0e37a2f0d53f23ae380bd840f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,7 +2,7 @@ <resources> <string name="hello">---</string> - <string name="app_name">NS 640g Uploader</string> + <string name="app_name">600 Series Uploader</string> <string name="eula_title">Disclaimer</string> <string name="eula_accept">Accept</string> <string name="eula_refuse">Refuse</string> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index de93838a97ceafac7a7701ecfbb6ee914ed9c5c3..ff89a6f2bb0e9027c0f4fc857a79595b7a6fe4d5 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -70,6 +70,10 @@ android:dialogTitle="Enter your Nightscout API secret" android:key="@string/preference_api_secret" android:title="API Secret"/> + <Preference android:title="scan NS-Autoconfig QR-Code" + android:key="scanButton" + android:dependency="@string/preference_enable_rest_upload" + android:summary="Click here to scan QR-Code from http://nightscout.github.io/pages/configure/ using ZXing barcode scanner."/> <CheckBoxPreference android:key="@string/preference_enable_xdrip_plus" android:summary="Enable local broadcast of data to xDrip+" diff --git a/app/update.json b/app/update.json new file mode 100644 index 0000000000000000000000000000000000000000..4c58d9459cd6887fd236f5890d94bb16a77243f8 --- /dev/null +++ b/app/update.json @@ -0,0 +1,10 @@ +{ + "latestVersion": "0.4.0", + "latestVersionCode": "7", + "url": "https://github.com/pazaan/600SeriesAndroidUploader/releases", + "releaseNotes": [ + "- Remove dependency on CareLink login. No more CareLink login issues!", + "- Local broadcasting to xDrip+", + "- Stability fixes" + ] +} diff --git a/build.gradle b/build.gradle index fa343792dd739dcc26b1521ca4931cdda922476f..9293e06bf74252a9284ab30257171f36c7a34199 100644 --- a/build.gradle +++ b/build.gradle @@ -5,10 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - classpath 'io.realm:realm-gradle-plugin:2.2.2' + classpath 'com.android.tools.build:gradle:2.3.1' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3d5435e07e9964062e47fc0426eaa27552a17041..8e8e1988d58c6650b6e10423666fdeef466bac95 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Nov 12 11:44:13 AEDT 2016 +#Tue Mar 28 09:13:19 AEDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip